diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000000..1cd9745822
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,4 @@
+/articles/quickstart @auth0/dx-sdks-engineer
+/articles/libraries @auth0/dx-sdks-engineer
+/articles/cms @auth0/dx-sdks-engineer
+/articles/quickstart/webapp/express @pdillon
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 49861ab9d9..bd61ed03a3 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,8 +1,3 @@
diff --git a/.github/workflows/check-content-version.yml b/.github/workflows/check-content-version.yml
new file mode 100644
index 0000000000..8d471da8b9
--- /dev/null
+++ b/.github/workflows/check-content-version.yml
@@ -0,0 +1,22 @@
+name: Check Content Version
+
+on:
+ schedule:
+ - cron: '0 * * * *' # Runs every hour
+ workflow_dispatch: # Allows manual trigger from GitHub Actions tab
+
+jobs:
+ run-script:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Make script executable
+ run: chmod +x scripts/check-version.sh
+ shell: bash
+
+ - name: Run check-version.sh script
+ run: scripts/check-version.sh
+ shell: bash
\ No newline at end of file
diff --git a/.github/workflows/clean-redirects-pr.yml b/.github/workflows/clean-redirects-pr.yml
new file mode 100644
index 0000000000..06b704805c
--- /dev/null
+++ b/.github/workflows/clean-redirects-pr.yml
@@ -0,0 +1,34 @@
+# Cleanup redirects config file.
+name: Redirects cleanup PR
+
+on:
+ schedule:
+ - cron: '0 7 * * 1'
+ workflow_dispatch:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Get current date
+ id: date
+ run: echo "current_date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
+ - name: Checkout
+ uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: '14.17'
+ cache: 'yarn'
+ - run: yarn
+ - run: yarn run clean-redirects
+ - name: Create Pull Request
+ id: cpr
+ uses: peter-evans/create-pull-request@v3
+ with:
+ commit-message: Redirects config cleanup ${{ env.current_date }}
+ committer: GitHub
+ author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
+ signoff: false
+ branch: clean_redirects_action_${{ env.current_date }}
+ delete-branch: true
+ title: 'Redirects config cleanup ${{ env.current_date }}'
\ No newline at end of file
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
new file mode 100644
index 0000000000..3c1be5f76d
--- /dev/null
+++ b/.github/workflows/integration-tests.yml
@@ -0,0 +1,34 @@
+name: Integration Tests
+on:
+ pull_request:
+ branches: master
+
+concurrency:
+ group: pr-integration-tests-${{ github.event.pull_request.id }}
+ cancel-in-progress: true
+
+jobs:
+ tests:
+ name: Trigger Tests
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Get branch name
+ id: branch-name
+ uses: tj-actions/branch-names@6c999acf206f5561e19f46301bb310e9e70d8815 # v7.0.7 on 2025-03-20
+ - name: Wait for Tests Results
+ uses: convictional/trigger-workflow-and-wait@v1.6.1
+ with:
+ owner: ${{ secrets.NOTIFY_ORG }}
+ repo: ${{ secrets.NOTIFY_REPO }}
+ github_token: ${{ secrets.NOTIFY_PAT_TOKEN }}
+ workflow_file_name: integration-tests.yml
+ ref: master
+ wait_interval: 90
+ client_payload: '{ "docsBranch": "${{ steps.branch-name.outputs.current_branch }}", "pullRequest": "${{ github.event.pull_request.number }}", "postStatus": "true" }'
+ propagate_failure: true
+ trigger_workflow: true
+ wait_workflow: true
diff --git a/.github/workflows/push-notify.yml b/.github/workflows/push-notify.yml
new file mode 100644
index 0000000000..a47e96380d
--- /dev/null
+++ b/.github/workflows/push-notify.yml
@@ -0,0 +1,21 @@
+name: Push Notify
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - master
+jobs:
+ dispatch:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Webhook Notify
+ uses: actions/github-script@v6
+ with:
+ github-token: ${{ secrets.NOTIFY_PAT_TOKEN }}
+ script: |
+ await github.rest.repos.createDispatchEvent({
+ owner: '${{ secrets.NOTIFY_ORG }}',
+ repo: '${{ secrets.NOTIFY_REPO }}',
+ event_type: 'docs_repo_webhook'
+ })
\ No newline at end of file
diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml
new file mode 100644
index 0000000000..19d6073644
--- /dev/null
+++ b/.github/workflows/semgrep.yml
@@ -0,0 +1,15 @@
+name: Semgrep
+on:
+ pull_request: {}
+jobs:
+ semgrep:
+ name: Scan
+ runs-on: ubuntu-latest
+ container:
+ image: returntocorp/semgrep
+ if: (github.actor != 'dependabot[bot]' && github.actor != 'snyk-bot')
+ steps:
+ - uses: actions/checkout@v3
+ - run: semgrep ci
+ env:
+ SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 3cc3b832ec..58ce0eb185 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,17 @@ config.json
# IDE
.idea
+
+# Visual Studio Code
+.vscode
+
+# Sublime Text
+*.sublime-project
+*.sublime-workspace
+
+# Vim
+*.swp
+*.swo
+Session.vim
+.netrwhist
+.vscode
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000000..6e01ce3ba0
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,6 @@
+{
+ "singleQuote": true,
+ "arrowParens": "always",
+ "printWidth": 120,
+ "trailingComma": "es5"
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 0aa52fd8a6..0000000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,4 +0,0 @@
-// Place your settings in this file to overwrite default and user settings.
-{
- "editor.formatOnSave": false
-}
diff --git a/.vscode/spell.json b/.vscode/spell.json
deleted file mode 100644
index e5133a8669..0000000000
--- a/.vscode/spell.json
+++ /dev/null
@@ -1 +0,0 @@
-{"language":"en","ignoreWordsList":["NuGet","RS256","Auth0","GitHub"],"mistakeTypeToStatus":{"Passive voice":"Hint","Spelling":"Error","Complex Expression":"Disable","Hidden Verbs":"Information","Hyphen Required":"Disable","Redundant Expression":"Disable","Did you mean...":"Disable","Repeated Word":"Warning","Missing apostrophe":"Warning","Cliches":"Disable","Missing Word":"Disable","Make I uppercase":"Warning"},"languageIDs":["markdown","text"],"ignoreRegExp":["/\\(.*\\.(jpg|jpeg|png|md|gif|JPG|JPEG|PNG|MD|GIF)\\)/g","/((http|https|ftp|git)\\S*)/g"]}
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d6866c05e4..0418e709cf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,7 +42,7 @@ The following is a set of guidelines for contributing to the Auth0 documentation
* Read and follow the [Style Guide](STYLEGUIDE.md).
* Consult the [Words](WORDS.md) document for Auth0 specific spellings and definitions.
* Always use relative URLs for internal `auth0.com/docs` links. For example, if the absolute path to the document is `https://auth0.com/docs/identityproviders`, use `/identityproviders`. These links will be correctly formatted in the build process.
-* Do not hard code links to Auth0 sites like `docs.auth0.com` or `manage.auth0.com`. Instead, use [Parameter Aliases](#parameter-aliases), such as `${manage_url}`.
+* Do not hard code links to Auth0 sites like `docs.auth0.com` or `manage.auth0.com`. Instead, use [Document Variables](#document-variables), such as `${manage_url}`.
* Name files with all lowercase using dashes (-) to separate words. If using a date in the file name, it should be in the format YYYY-MM-DD. For example, `this-is-my-file.md` or `this-is-a-title-2015-10-01.md`.
* Do not store images in external locations like Dropbox, CloudUp, or the Auth0 CDN. Link to images in this repo using a relative path ``. The image will be uploaded to the CDN and the link will be formatted during the build process. Do not forget to set the alternate text for each image.
* Keep images to no more than 750 pixels wide.
@@ -69,11 +69,33 @@ Additionally, you can send variables to the included document:
## Markdown
-Markdown on this site conforms to the [CommonMark](http://commonmark.org/) spec. Additionally, there are a few custom markdown features available as described below.
+Markdown on this site conforms to the [CommonMark](http://commonmark.org/) spec. Additionally, there are a few custom Markdown features available as described below.
+
+You should [test your Markdown](http://markdownlivepreview.com) to ensure the formatting is correct.
### Headings
-One common mistake with formatting of headings is to not include a space between the hashes and the text. Some markdown processors allow this, but we do not. You must put a space as shown below.
+Add one to six `#` symbols before your heading text to create your header. The number of # you use determines the size of the heading.
+
+```
+# H1
+## H2
+### H3
+#### H4
+##### H5
+###### H6
+```
+
+The header text above renders as follows:
+
+# H1
+## H2
+### H3
+#### H4
+##### H5
+###### H6
+
+One common mistake with formatting of headings is to not include a space between the hashes and the text. Some Markdown processors allow this, but we do not. You must put a space as shown below.
INVALID: `#My Heading`
@@ -82,8 +104,8 @@ VALID: `# My Heading`
### UI Components
General advice:
-- Don't add custom UI components with HTML unless it's really necessary.
-- Don't add any element before the main title. If you want to show some general information for the whole doc put the element after the main title.
+- Do not add custom UI components with HTML unless it's really necessary.
+- Do not add any element before the main title. If you want to show some general information for the whole doc put the element after the main title.
- Try to keep the amount of UI components on your docs to a minimum. They make the documentation more difficult to read and cut the reading flow.
- Only use the `blockquote` element (`>` in markdown) to represent actual quotes. Use a `note` or a `panel` if you want to highlight the information.
@@ -95,7 +117,7 @@ Only use this if the content is brief (one to four lines), if not use the `panel
```markdown
::: note
- If you need a refresher on the OAuth 2.0 protocol, you can go through our OAuth 2.0 article.
+If you need a refresher on the OAuth 2.0 protocol, you can go through our OAuth 2.0 article.
:::
```
@@ -145,7 +167,7 @@ Description
:::
::: panel-warning Security Warning
-It is important to understand that the Authorization Code flow should only be used in cases such as a Regular Web Application where the Client Secret can be safely stored. In cases such as a Single Page Application, the Client Secret is available to the client (in the web browser), so the integrity of the Client Secret cannot be maintained. That is why the [Implicit Grant flow](/api-auth/grant/implicit) is more appropriate in that case.
+It is important to understand that the Authorization Code flow should only be used in cases such as a Regular Web Application where the Client Secret can be safely stored. In cases such as a Single-Page Application, the Client Secret is available to the client (in the web browser), so the integrity of the Client Secret cannot be maintained. That is why the [Implicit Flow](/flows/concepts/implicit) is more appropriate in that case.
:::
```
@@ -168,7 +190,7 @@ Try to keep the list length to a minimum (up to 5 links).

### HTTP Request Snippets
-You can add a [HAR request format](http://www.softwareishard.com/blog/har-12-spec/#request) snippet to make an example HTTP request availible in a variety of languages. This will generate a tab view showing the HTTP request in various languages.
+You can add a [HAR request format](http://www.softwareishard.com/blog/har-12-spec/#request) snippet to make an example HTTP request available in a variety of languages. This will generate a tab view showing the HTTP request in various languages.
The library we use is [HTTP Snippet](https://github.com/Kong/httpsnippet).
@@ -266,7 +288,7 @@ For close-ups and other screenshots that do not include the browser window, appl
You can set various properties of articles in the front matter of the document. Each document should have the `title` and `description` properties set. You can set other variables depending on the document.
-`toc` adds a table of content dropdown at the top of the document, that lists all the paragraphs of the doc. By default it's disabled. Set it to `true` to display the dropdown.
+`toc` adds a table of content dropdown at the top of the document, that lists all the paragraphs of the doc. By default it is disabled. Set it to `true` to display the dropdown.
Example front matter:
@@ -280,7 +302,7 @@ toc: true
#### URLs
-Document urls are by default in the same format as the forlder structure after the `articles` folder. So for example if you document is stored at `articles/my-folder/document.md`, the url would be `/docs/my-folder/document`.
+Document urls are by default in the same format as the folder structure after the `articles` folder. So for example if you document is stored at `articles/my-folder/document.md`, the url would be `/docs/my-folder/document`.
If you create a folder that will have multiple articles, the best practice is to set the default document as `index.md`. However, the url must be set in that document to a friendly url. For example, if you have a document `/articles/my-folder/index.md`, you should set the url to be `/my-folder`.
@@ -297,14 +319,14 @@ url: /path/to/document
We use a pre-commit hook that lints the edited files to ensure a consistent style in the docs.
We use [markdownlint](https://github.com/DavidAnson/markdownlint) with the rules specified in the `.markdownlint.json` file in the root of the repo to do this. You can [check more about the linting rules](https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md).
-You won't be able to commit if your edited file don't follow these guidelines.
+You will not be able to commit if your edited file does not follow these guidelines.
-If you are using VS Code as your code editor, it's highly recommended to install the [MarkdownLint VS Code Extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint).
+If you are using VS Code as your code editor, it is highly recommended to install the [MarkdownLint VS Code Extension](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint).
## Sidebar
When you are adding a new article you should always add a link to it in the `config/sidebar.yml` file.
-It's really important to represent all our articles in the sidebar because this will help the user see where they are inside the documentation.
+It is really important to represent all our articles in the sidebar because this will help the user see where they are inside the documentation.
You can add titles to the sidebar using the attribute `category`:
@@ -368,11 +390,11 @@ To create and submit a job to Wordy:
You will need to provide the following pieces of information:
* **Language**: Set to *English (US)*.
-* **Content rewrite**: Select this option if you are okay with your editor rewriting your text for improved flow and natural use of langauge. If this option is *not* selected, your editor will simply check for spelling, grammar, punctuation, consistency, and structure.
-* **Brief to editor**: Provide any information you'd like your editor to keep in mind when editing your work. For a starter snippet, please see our sample on [Notes to Wordy Editors](wordy-guide.md)
+* **Content rewrite**: Select this option if you are okay with your editor rewriting your text for improved flow and natural use of language. If this option is *not* selected, your editor will simply check for spelling, grammar, punctuation, consistency, and structure.
+* **Brief to editor**: Provide any information you would like your editor to keep in mind when editing your work. For a starter snippet, please see our sample on [Notes to Wordy Editors](wordy-guide.md)
* **Save my brief and language settings for future jobs**: Select this box to persist your chosen settings.
5. Upload files. You may choose to upload external files containing your text or paste in the text you want edited.
-6. After you've completed the above steps, you'll get an instant price quote and an approximate delivery time for your job. If this is acceptable to you, click on **Create Job** to begin the editing process.
+6. After you have completed the above steps, you will get an instant price quote and an approximate delivery time for your job. If this is acceptable to you, click on **Create Job** to begin the editing process.
### Word Count and Wordy Submissions
@@ -386,7 +408,7 @@ It is helpful to include some instructions for the Wordy editors to let them kno
### Notes
-* You can cancel a job if it hasn’t been picked up by an editor. If the job has been picked up, you can contact the editor and request a cancellation, though it is at the editor's discretion whether or not to cancel the job.
+* You can cancel a job if it has not been picked up by an editor. If the job has been picked up, you can contact the editor and request a cancellation, though it is at the editor's discretion whether or not to cancel the job.
* During the editing process, you can contact your editor from the job's page. You can include last-minute instructions, corrections, and so on. Conversely, your editor can contact you during the process if they have any questions about your text. You will be notified by email if you receive any messages.
* If you are unsatisfied with the work completed by your editor, you can send your work back. This includes issues where you find errors in the text or the instructions in your brief haven't been followed. You can contact your editor by using the **Conversation History** feature on the job's page.
@@ -474,7 +496,7 @@ hidden_articles:
### Quickstart Guidelines
-Each framework will have a set of articles that comprise the quickstarts. The set of articles each framework will have depends on the function of each. Below is an outline of the documentats that should be created for each framework.
+Each framework will have a set of articles that comprise the quickstarts. The set of articles each framework will have depends on the function of each. Below is an outline of the documents that should be created for each framework.
#### Library References
@@ -484,19 +506,19 @@ Additionally, many libraries may also need manual documentation showing more sop
#### Quickstarts Articles
-Each framework will have a set of articles that comprise the quickstarts. The set of articles each framework will have depends on the function of each. Below is an outline of the documentats that should be created for each framework.
+Each framework will have a set of articles that comprise the quickstarts. The set of articles each framework will have depends on the function of each. Below is an outline of the documents that should be created for each framework.
##### Native
0. Intro - Introduction and summary of what the quickstart is about and a Table of Contents
1. Login - Shows how to create an auth0 application, add the login widget to your code, setup everything, and perform a login.
2. Login with Custom UI - Using head-less library to do login without Lock
-3. Session Handling - How to store tokens, refresh tokens, and logout
+3. Session Handling - How to store tokens, Refresh Tokens, and logout
4. User Profile - How to access the user profile from within the app. The core concepts of this are how to retrieve profile data as well as any claims that are present in the token.
5. Linking Accounts - How to link two accounts using both the lock widget or using the API manually.
6. Rules - Using rules to change what is in the token. This document is likely shared with all quickstarts[a].
7. Authorization - How to pull scope or other access control claims from the token and use those claims to authorize a user to perform certain actions in the application.[b]
-8. Calling Your API - How to take the access token from
+8. Calling Your API - How to take the Access Token from
9. MFA - how to add MFA to your app. This should probably be a single document that is shared with all native apps[c].
10. Customizing Lock - Document explaining the basics of how to custom lock. There are full documents about this as well that show the complete details.
@@ -510,7 +532,7 @@ Each framework will have a set of articles that comprise the quickstarts. The se
5. Linking Accounts - How to link two accounts using both the lock widget or using the API manually.
6. Rules - Using rules to change what is in the token. This document is likely shared with all quickstarts.
7. Authorization - How to pull scope or other access control claims from the token and use those claims to authorize a user to perform certain actions in the application.
-8. Multifactor Authentication - how to add MFA to your app. This should probably be a single document that is shared with all native apps.
+8. Multi-factor Authentication - how to add MFA to your app. This should probably be a single document that is shared with all native apps.
9. Customizing Lock - Document explaining the basics of how to custom lock. There are full documents about this as well that show the complete details.
##### SPA
@@ -523,7 +545,7 @@ Each framework will have a set of articles that comprise the quickstarts. The se
5. Linking Accounts - How to link two accounts using both the lock widget or using the API manually.
6. Rules - Using rules to change what is in the token. This document is likely shared with all quickstarts.
7. Authorization - How to pull scope or other access control claims from the token and use those claims to authorize a user to perform certain actions in the application. This section will include information on how to use rules and authorization together.
-8. Calling Your API - How to take the access token from
+8. Calling Your API - How to take the Access Token from
9. MFA - how to add MFA to your app. This should probably be a single document that is shared with all native apps.
10. Customizing Lock - Document explaining the basics of how to customize lock. There are full documents about this as well that show the complete details.
@@ -534,7 +556,7 @@ Each framework will have a set of articles that comprise the quickstarts. The se
#### Libraries
-As appropriate every framework/language should have libraries to help with common functions. THese libraries will include things like:
+As appropriate, every framework/language should have libraries to help with common functions. These libraries will include things like:
* Management API Libraries
* Authentication API Libraries
@@ -563,7 +585,7 @@ In this way, each section of the quickstart has a sample showing the appropriate
##### Sample README’s
-The README for each sample folder should be written to reflect the objectives of the sample and should also show some important code snippets. The goal is to give the reader context in a quick and concise way while outlining exactly what learning outcomes can be expected. It’s important to make content within each README specific to the subject sample.
+The README for each sample folder should be written to reflect the objectives of the sample and should also show some important code snippets. The goal is to give the reader context in a quick and concise way while outlining exactly what learning outcomes can be expected. It is important to make content within each README specific to the subject sample.
* **Example**: 02-User-Profile
* **Title**: “User Profile”
@@ -587,18 +609,18 @@ Each sample repo should have appropriate CI setup. You should use the appropriat
In the case of things like iOS and Android samples, we should build with multiple version of Android/Xcode, etc. You can see an example here:
1. No need to write code or specialized guide for mobile
-2. We don't have a lot of stuff finished to be doing this one in mobile.
+2. We do not have a lot of stuff finished to be doing this one in mobile.
3. No need to write code or specialized guide for mobile until we allow users to enroll mfa from mobile apps. Currently is web only
### Seed Projects
-Each quickstart should have a seed project. The seed projects are hosted in github in the `auth0-samples` organization. In order to add a seed project to a quickstart simply use the `_package` include.
+Each quickstart should have a seed project. The seed projects are hosted on github in the `auth0-samples` organization. In order to add a seed project to a quickstart simply use the `_package` include.
The seed project packager service replaces placeholder configuration values with the values of the user's real application. This means the sample is ready to use without additional configuration. The strings that get set are shown below.
These values can be replaced in any file in the repo. Common examples of where you would include these values are in a `.env` file or `auth0-variables.js` file. In addition to replacement in the file directly, you can also include a template file in the form of `filename.ext.example` such as `auth0-variables.js.example`. The packager will do the replacement and remove the `.example` extension from the file.
-**NOTE:** It is a best practice to use the `.example` method and include the 'real' file in the '.gitignore' so that if the end-user turns the sample into a git repo, the Auth0 keys wont get checked into source control. You should include the `.gitignore` file in the actual seed project folder, not at the repo root. This way it is included in the seed package.
+**NOTE:** It is a best practice to use the `.example` method and include the 'real' file in the '.gitignore' so that if the end-user turns the sample into a git repo, the Auth0 keys won't get checked into source control. You should include the `.gitignore` file in the actual seed project folder, not at the repo root. This way it is included in the seed package.
| Key Name | Replace Value | Description |
| :------| :-----------| :-----------|
@@ -608,7 +630,7 @@ These values can be replaced in any file in the repo. Common examples of where y
| `TENANT` | `{TENANT}` | The tenant name of the currentAuth0 account.
| `CALLBACK_URL` | `{CALLBACK_URL}` | This sets the callback url for the application. |
| `MOBILE_CUSTOM_SCHEME` | `{MOBILE_CUSTOM_SCHEME}` | This a unique ID for mobile apps. The string is `a0` + the value of the client ID. |
-| `RANDOM_STRING_64` | `{RANDOM_STRING_64}` | This is a random string. Typically used for things like encryption keys, etc. For security reasons we set this with a reasonable default so if end-users forget to change them, they wont all be something like `YOUR_ENCRYPTION_KEY`. |
+| `RANDOM_STRING_64` | `{RANDOM_STRING_64}` | This is a random string. Typically used for things like encryption keys, etc. For security reasons, we set this with a reasonable default so if end-users forget to change them, they won't all be something like `YOUR_ENCRYPTION_KEY`. |
Example `.env` file:
@@ -757,10 +779,9 @@ When writing docs you can use the following variables instead of hard-coding the
| Variable | Description | Default Value |
| :---------------------------- | :----------------------------------------- | :-------------------------------------- |
| `manage_url` | The url to the management portal. | `https://manage.auth0.com` |
-| `auth0js_url` | The url to the auth0.js v7 CDN location. | |
+| `auth0js_url` | The url to the auth0.js CDN location. | |
| `auth0js_urlv8` | The url to the auth0.js v8 CDN location. | |
| `lock_url` | The url to the Lock script CDN location. | |
-| `lock_passwordless_url` | The url to the Passwordless Lock script CDN location. | |
| `env.DOMAIN_URL_SUPPORT` | Support Center URL | `https://support.auth0.com` |
### User Specific Variables
@@ -867,7 +888,7 @@ example/
index.yml
```
-This limitation is a result of the implementation of `AutoVersionPlugin`, and how the paths are calculated for the different versions. Fixing this is possible, but makes things a little more tricky, so I decided to cut it from the first version of the feature. If it's a desired behavior we can always add it later.
+This limitation is a result of the implementation of `AutoVersionPlugin`, and how the paths are calculated for the different versions. Fixing this is possible, but makes things a little more tricky, so I decided to cut it from the first version of the feature. If it is a desired behavior we can always add it later.
#### Case Sensitive
diff --git a/LICENSE b/LICENSE
index 0d651713af..9595798aa0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2015 Auth0, Inc. (http://auth0.com)
+Copyright (c) 2015-present Auth0, Inc. (http://auth0.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 46ec9f5e12..1388ddcc84 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,29 @@
# Auth0 Documentation
-This is the repository for the Auth0 documentation.
+
+This repository contains the Auth0 Quickstarts, but most other documentation content in this repository is no longer up to date, and is not the source of content at https://auth0.com/docs. Pull requests and issues for Quickstarts can still be submitted here, but most other content is no longer hosted on GitHub and therefore no longer open-source. If you are an Auth0 employee trying to make a change to other documentation, please [submit a ticket](https://auth0team.atlassian.net/servicedesk/customer/portal/9) or contact the Documentation Team to request access to our content management system.
+
**Please review the [Contributing Guidelines](CONTRIBUTING.md) before sending a PR or opening an issue.**
-## Running the Docs Site
-You can run and test the docs site locally (you will need access - only employees). For instructions on running the site and testing see the [README](https://github.com/auth0/auth0-docs/blob/master/README.md) (requires Auth0 team access).
+* If you are looking for the application that *hosts* the Docs content, see [auth0-docs](https://github.com/auth0/auth0-docs).
+* If you would like to modify the Management API v2 API docs, they are generated from the [api2](https://github.com/auth0/api2) repository.
+
+Both of the above repositories require team access.
+
+## Editing Docs Content
+Auth0 Docs are no longer maintained in this Github repository. Employees can request access to our content management system to update Docs directly. Outside contributors can submit requests under the [Issues](https://github.com/auth0/docs/issues) section in this repository.
+
+## Editing Quickstart Content
+
+* You can edit the Quickstarts by using the GitHub web editor and editing a file. This is best suited for typos and small changes.
+* You can also pull down the `/docs` repo to your computer via Git and edit files in your local editor before pushing a new branch (or a branch to your own fork of the project). You can then go to GitHub.com and start a PR. We will be able to review the changes in a Heroku test application prior to merging.
+* Lastly, you can [run and test the docs site locally](https://github.com/auth0/auth0-docs/blob/master/README.md) (access available to Auth0 employees only). This option is best suited for repeat contributors or for complex contributions. You gain the benefit of locally testing and viewing your changed or added pages, navigation, and config, but you also gain the complexity of dealing with the local docs app, setting it up, and keeping it updated.
+
+Regardless of which option you use, please review any relevant sections of the [Contributing Guidelines](CONTRIBUTING.md) before sending a PR.
## Issue Reporting
-If you found a bug or have a feature request, please report it in this repository's [issues](https://github.com/auth0/docs/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.
+If you find a bug or inaccuracy in the documentation content, please report it in this repository's [issues](https://github.com/auth0/docs/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.
## Author
diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md
index 65e8b094e0..12a59bbc8c 100644
--- a/STYLEGUIDE.md
+++ b/STYLEGUIDE.md
@@ -2,59 +2,59 @@
This style guide covers the terminology and content specific to Auth0, along with some comments on common writing issues.
-For general software-industry styles and terminology, see the [Microsoft Manual of Style](https://eucalyptus.atlassian.net/wiki/download/attachments/76611622/microsoft_manual_of_style_fourth_edition.pdf?version=2&modificationDate=1424379604164&api=v2).
+For general software-industry styles and terminology, see the [Microsoft Writing Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/).
## Voice
-* Address the reader directly: "you". Use "we" only for Auth0's recommendations.
-* Use active voice.
-* For instructions, use imperative mood.
+* Address the reader directly: "you". Use "we" only for Auth0's recommendations.
+* Use the active voice.
+* For instructions, use the imperative mood.
| **Incorrect** | **Correct** |
| --- | --- |
| User authentication data should be saved.| Save user authentication data. |
-| Saving user authentication data is recommended. | We recommend that you save user authentication data. |
+| Saving user authentication data is recommended. | We recommend that you save user authentication data. |
-* Use gender-neutral pronouns: "they", "their".
+* Use gender-neutral pronouns: "they", "their".
| **Incorrect** | **Correct** |
| --- | --- |
| The user enters his password. | The user enters their password. |
-* Avoid gerunds in headings and main body.
+* Avoid gerunds in headings and the main body.
| **Incorrect** | **Correct** |
| --- | --- |
-| Saving User Authentication Data | Save User Authentication Data |
-| Setting up the authorization process requires an ID token and a valid access token. | To set up the authorization process, you need an ID token and a valid access token. |
+| Saving User Authentication Data. | Save User Authentication Data. |
+| Setting up the authorization process requires an ID Token and a valid Access Token. | To set up the authorization process, you need an ID Token and a valid Access Token. |
## Body text
-* Keep paragraphs short for internet reading.
+* Keep paragraphs short for internet reading.
* Provide only the information necessary to understand and perform the steps.
| **Incorrect** | **Correct** |
| --- | --- |
| Authentication using JSON Web Tokens is stateless by nature, meaning that there is no information about the user's session stored on your server.| Authentication using JSON Web Tokens is stateless. This means that when you use it, no information about user session is stored on your server. |
-| In this way, setting up a session for the user on the client side is simply a matter of saving the `access_token`, `id_token`, and a time that the `access_token` expires at in browser storage. | To set up a session for the user on the client side, save the following information in browser storage: `access_token`, `id_token`, `expires_in`. |
+| In this way, setting up a session for the user on the client side is simply a matter of saving the Access Token, ID Token, and a time that the Access Token expires at in browser storage. | To set up a session for the user on the client side, save the following information in browser storage: `access_token`, `id_token`, `expires_in`. |
-* When mentioning several elements, use bulleted lists.
-* Subheads are not independent statements. Repeat the information from the subhead in the paragraph.
+* When mentioning several elements, use bulleted lists.
+* Subheads are not independent statements. Repeat the information from the subhead in the paragraph.
* Avoid abbreviations.
| **Incorrect** | **Correct** |
| --- | --- |
| Don't hardcode paths in your application, e.g., the callback URL. | Don't hardcode paths in your application, for example, the callback URL. |
-| Save all the important credentials: the access token, the refresh token, etc. in a safe location. | Save all the important credentials, such as the access and refresh token, in a safe location. |
+| Save all the important credentials: the Access Token, the Refresh Token, etc. in a safe location. | Save all the important credentials, such as the Access and Refresh Token, in a safe location. |
-* Avoid contractions. Use complete words to be more authoritative.
+* Avoid contractions. Use complete words to be more authoritative.
| **Incorrect** | **Correct** |
| --- | --- |
| Can't | Cannot |
* Don't overuse adjectives. Never use more than two in a sentence.
-* Don't overuse adverbs.
+* Don't overuse adverbs.
| **Incorrect** | **Correct** |
| --- | --- |
@@ -64,21 +64,21 @@ For general software-industry styles and terminology, see the [Microsoft Manual
## Punctuation
* Use colons to introduce code or examples: "Install the dependencies using yarn: `code_snippet`"
-* Use hyphens between adjectives and the verbs they modify. Don't use a hyphen if the adjective ends with "ly".
+* Use hyphens between adjectives and the verbs they modify. Don't use a hyphen if the adjective ends with "ly".
| **Incorrect** | **Correct** |
| --- | --- |
| "an easy to remember rule" | "an easy-to-remember rule" |
| "commonly-used adjectives" | "commonly used adjectives" |
-* When you are quoting something in a sentence, keep the punctuation inside the quotation marks.
-* When you are quoting code, do not add any punctuation inside the quotation marks.
+* When you are quoting something in a sentence, keep the punctuation inside the quotation marks.
+* When you are quoting code, do not add any punctuation inside the quotation marks.
## Formatting
* Use title case for first-level headings: "Log In with a Social Identity"
* Use sentence case for subheads: "About the login process"
-* Use **Bold** for UI elements, such as menu items and field names.
+* Use **Bold** for UI elements, such as menu items and field names.
| **Incorrect** | **Correct** |
| --- | --- |
@@ -90,17 +90,17 @@ For general software-industry styles and terminology, see the [Microsoft Manual
| **Incorrect** | **Correct** |
| --- | --- |
| Save the "idToken" value in your client properties. | Save the `idToken` value in your client properties. |
-| An `idToken` helps you identify the user. | An ID token helps you identify the user. |
+| An `idToken` helps you identify the user. | An ID Token helps you identify the user. |
-* The text of a link must include the title of the linked page. This helps the reader decide if they want to click on the link.
+* The text of a link must include the title of the linked page. This helps the reader decide if they want to click on the link.
| **Incorrect** | **Correct** |
| --- | --- |
| You can read more about this feature [here](/rules). | Read more about this feature in the [Rules documentation](/rules). |
* Use blockquotes only for quotes. Don't use them for component styles.
-* When you are referring to specific dates, abbreviate the following months: January (Jan.), February (Feb.), August (Aug.), September (Sept.), October (Oct.), November (Nov.), December (Dec.).
-* When you are referring to a month alone or a month and a year, don't abbreviate the month.
+* When you are referring to specific dates, abbreviate the following months: January (Jan.), February (Feb.), August (Aug.), September (Sept.), October (Oct.), November (Nov.), December (Dec.).
+* When you are referring to a month alone or a month and a year, don't abbreviate the month.
| **Incorrect** | **Correct** |
| --- | --- |
@@ -110,10 +110,20 @@ For general software-industry styles and terminology, see the [Microsoft Manual
| Mar. 15 | March 15 |
| 15 March 2048 | March 15, 2048 |
-* Spell out whole numbers from zero to nine.
-* Write numerically numbers from 10 up and fractions.
-* Spell out any number that starts a sentence.
-* If one number follows another immediately, spell out the first number.
+* Endpoint names should be capitalized when used in-text: Discovery endpoint, Authorization endpoint, Token endpoint.
+* Endpoints with names longer than one or two words should also be capitalized with the exception of prepositions and articles (i.e. with, to, the, a, an) such as Update a Hook endpoint.
+* Endpoint names denoted as a path should not be capitalized but should be in monospace font: `/authorize,` `/post_user_import,` `/clients.`
+
+| **Incorrect** | **Correct** |
+| --- | --- |
+| You will need to access the discovery endpoint. | You will need to access the Discovery endpoint.|
+| The get user endpoint allows you to search based on a variety of criteria. | The Get User endpoint allows you to search based on a variety of criteria. |
+| The POST /login/callback endpoint can accept a sing-on SAML request from an identity provider. | The POST '/login/callback' endpoint can accept a sing-on SAML request from an identity provider. |
+
+* Spell out whole numbers from zero to nine.
+* Write numerically numbers from 10 up and fractions.
+* Spell out any number that starts a sentence.
+* If one number follows another immediately, spell out the first number.
| **Incorrect** | **Correct** |
| --- | --- |
@@ -122,16 +132,16 @@ For general software-industry styles and terminology, see the [Microsoft Manual
| 14 plugins are available. | Fourteen plugins are available. |
| Configure 12 50GB drives | Configure twelve 50GB drives. |
-* For additional information that is up to four lines long, use [notes](/blob/master/CONTRIBUTING.md#note).
-* For additional information that is longer than four lines, use [panels](https://github.com/auth0/docs/blob/master/CONTRIBUTING.md#panels).
-* For critical security information up to four lines long, use [warnings](https://github.com/auth0/docs/blob/master/CONTRIBUTING.md#warning).
-* For critical security information longer than four lines, use [panel warnings](https://github.com/auth0/docs/blob/master/CONTRIBUTING.md#panel-warning).
+* For additional information that is up to four lines long, use [notes](CONTRIBUTING.md#note).
+* For additional information that is longer than four lines, use [panels](CONTRIBUTING.md#panels).
+* For critical security information up to four lines long, use [warnings](CONTRIBUTING.md#warning).
+* For critical security information longer than four lines, use [panel warnings](CONTRIBUTING.md#panel-warning).
## Vocabulary
-* If an action is required, use "must".
-* If an action is available, use "can".
-* If an action is optional, use "may".
+* If an action is required, use "must".
+* If an action is available, use "can".
+* If an action is optional, use "may".
| **Incorrect** | **Correct** |
| --- | --- |
@@ -139,8 +149,8 @@ For general software-industry styles and terminology, see the [Microsoft Manual
| You might want to use scopes to limit access to your resources. | To limit access to your resources, use scopes. |
| Creating more access roles is possible. | You may want to create more access roles. |
-* Use "log in" and "log out" as verbs. Do not use "log into".
-* Use "login" and "logout" as nouns. Do not use "login to".
+* Use "log in" and "log out" as verbs. Do not use "log into".
+* Use "login" and "logout" as nouns. Do not use "login to".
| **Incorrect** | **Correct** |
| --- | --- |
@@ -155,8 +165,8 @@ For general software-industry styles and terminology, see the [Microsoft Manual
| Setup the login screen. | Set up the login screen. |
| Edit the login screen set-up to display the **Log in** button. | Edit the login screen setup to display the **Log in** button. |
-* Use "multifactor authentication" instead of "multi-factor authentication".
-* Use "email address" instead of "e-mail address".
+* Use "multi-factor authentication" instead of "multifactor authentication".
+* Use "email address" instead of "e-mail address".
* Use "website" instead of "web site".
* Use "click on" when referring to text links in a webpage or UI. Use "click" when referring to a button.
@@ -166,7 +176,7 @@ For general software-industry styles and terminology, see the [Microsoft Manual
| Click **Go to Settings** at the bottom of the page to access the settings section. | Click on **Go to Settings** at the bottom of the page to access the settings section. |
* Depending on the situation, the reader can "gain access", "grant access", or "allow access".
-* Refer to the developer's customer as the "user".
+* Refer to the developer's customer as the "user".
* If you need to use the name of a fictional company, use "ExampleCo".
* When you use a group of nouns as an adjective, use a hyphen.
@@ -176,13 +186,13 @@ For general software-industry styles and terminology, see the [Microsoft Manual
| The run-time engine must be running to execute the application. | The runtime engine must be running to execute the application. |
| Write code for the client-side. | Write code for the client side. |
| Write the client side code. | Write the client-side code. |
-| Save the logged in user's access token. | Save the logged-in user's access token. |
+| Save the logged in user's Access Token. | Save the logged-in user's Access Token. |
### The dashboard
-* Dashboard: the [Auth0 management console](${manage_url})
-* The dashboard elements are called "section", "tab", "field".
-* Dashboard-related terminology:
+* Dashboard: the [Auth0 management console](${manage_url}).
+* The dashboard elements are called "section", "tab", "field".
+* Dashboard-related terminology:

### The application
@@ -191,4 +201,4 @@ For general software-industry styles and terminology, see the [Microsoft Manual
* Tenant: a logical isolation unit of the products we offer. Examples of Auth0 tenants: `foo.auth0.com`, `bar.auth0.com`
* Auth0 tenants: regular cloud tenants
* Subscription: a contract or service plan. Examples of subscriptions: trial, free, developer or developer-pro
-* Private instances: appliance instances
\ No newline at end of file
+* Private Cloud/Managed Private Cloud: single-tenant deployment
diff --git a/WORDS.md b/WORDS.md
index 6e754976ff..4764298894 100644
--- a/WORDS.md
+++ b/WORDS.md
@@ -4,7 +4,7 @@ This document contains spellings and definitions as they are to be used in the A
- **Login / Log in**: Use *log in* as a verb, or *login* as a noun. Do NOT use *log into* or *login to*.
- **Logout / Log out**: Use *log out* as a verb, or *logout* as a noun.
- **Setup / Set up**: Use *set up* as a verb, or *setup* as a noun.
-- **Multifactor**: Use instead of multi-factor in the case of multifactor authentication.
+- **Multi-factor**: Use *multi-factor* instead of *multifactor* in the case of multi-factor authentication.
- **Rollout / Roll out**: Use *rollout* as a noun and *roll out* as a verb. Do not use `roll-out`.
- **Email**: Use the un-hyphenated "email" to refer to an email address.
- **Click**: Use "Click on" when referring to text links in a webpage or UI, "Click" when referring to a button. For example: Click **Save**. Click on **This link**.
@@ -39,10 +39,10 @@ When writing about tokens, capitalize specific token names as follows:
* Access Token
* Refresh Token
-#### Within Appliance subscriptions
+#### Within Private Cloud subscriptions
* **Auth0 tenants** refers to regular cloud tenants
-* **Private instances** refers to appliance instances
+* **Private Cloud** or **Managed Private Cloud** refers to a single-tenant deployment
### TL;DR
diff --git a/app.json b/app.json
index 0b45ad2eb6..838727dbce 100644
--- a/app.json
+++ b/app.json
@@ -2,6 +2,12 @@
"name": "auth0-docs-content",
"scripts": {
},
+ "formation": {
+ "web": {
+ "quantity": 1,
+ "size": "standard-2x"
+ }
+ },
"env": {
"NPM_CONFIG_PRODUCTION": {
"required": true
@@ -15,6 +21,9 @@
"HEROKU_APP_NAME": {
"required": true
},
+ "HEROKU_PARENT_APP_NAME": {
+ "required": true
+ },
"GIT_SSH_KEY": {
"required": true
}
diff --git a/articles/_includes/_api-auth-customize-tokens.md b/articles/_includes/_api-auth-customize-tokens.md
index 460c8a3a61..0c5ca2a2e3 100644
--- a/articles/_includes/_api-auth-customize-tokens.md
+++ b/articles/_includes/_api-auth-customize-tokens.md
@@ -15,5 +15,5 @@ function(user, context, callback) {
```
::: panel-warning Namespacing Custom Claims
-Auth0 returns profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID Tokens or Access Tokens, they must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims) to avoid possible collisions with standard OIDC claims. For example, if you choose the namespace `https://foo.com/` and you want to add a custom claim named `myclaim`, you would name the claim `https://foo.com/myclaim`, instead of `myclaim`. You can [add namespaced claims using Rules](#optional-customize-the-tokens).
+Auth0 returns profile information in a [structured claim format as defined by the OpenID Connect (OIDC) specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID Tokens or Access Tokens, they must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims. You can [add namespaced claims using Rules](#optional-customize-the-tokens).
:::
diff --git a/articles/_includes/_api_auth_intro.md b/articles/_includes/_api_auth_intro.md
index ede006191a..c7b3365570 100644
--- a/articles/_includes/_api_auth_intro.md
+++ b/articles/_includes/_api_auth_intro.md
@@ -1,2 +1,3 @@
-This tutorial shows you how to use the authorization features in the OAuth 2.0 framework to limit access to your or third-party applications.
-For more information, read the [API authorization](/api-auth) documentation.
\ No newline at end of file
+::: note
+**New to Auth0?** Learn how Auth0 works and read about implementing API authentication and authorization using the OAuth 2.0 framework.
+:::
diff --git a/articles/_includes/_callback_url.md b/articles/_includes/_callback_url.md
index 662815992b..3d4851c568 100644
--- a/articles/_includes/_callback_url.md
+++ b/articles/_includes/_callback_url.md
@@ -1,5 +1,5 @@
-## Configure Callback URLs
+
-A callback URL is a URL in your application where Auth0 redirects the user after they have authenticated.
+### Configure Callback URLs
-You need to whitelist the callback URL for your app in the **Allowed Callback URLs** field in your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings). If you do not set any callback URL, your users will see a mismatch error when they log in.
\ No newline at end of file
+A callback URL is a URL in your application where Auth0 redirects the user after they have authenticated. The callback URL for your app must be added to the **Allowed Callback URLs** field in your Application Settings. If this field is not set, users will be unable to log in to the application and will get an error.
diff --git a/articles/_includes/_checksession_polling.md b/articles/_includes/_checksession_polling.md
new file mode 100644
index 0000000000..9030fb5770
--- /dev/null
+++ b/articles/_includes/_checksession_polling.md
@@ -0,0 +1,3 @@
+In some multi-application scenarios, where Single Logout is desired (a user logging out of one application needs to be logged out of other applications), an application can be set up to periodically poll Auth0 using `checkSession()` to see if a session exists. If the session does not exist, you can then log the user out of the application. The same polling method can be used to implement silent authentication for a Single Sign-on (SSO) scenario.
+
+The poll interval between checks to `checkSession()` should be at least 15 minutes between calls to avoid any issues in the future with rate limiting of this call.
diff --git a/articles/_includes/_co_authenticate_errors.md b/articles/_includes/_co_authenticate_errors.md
index 3f0ba837a4..af87d27465 100644
--- a/articles/_includes/_co_authenticate_errors.md
+++ b/articles/_includes/_co_authenticate_errors.md
@@ -12,7 +12,6 @@ The error description is human readable. It **should not be parsed by any code**
| 401 | unauthorized_client | Cross origin login not allowed. |
| 400 | unsupported_credential_type | Unknown credential type parameter. |
| 400 | invalid_request | Unknown realm non-existent-connection. |
-| 403 | access_denied | Invalid user credentials. |
| 403 | access_denied | Wrong email or password. |
| 403 | access_denied | Authentication error |
| 403 | blocked_user | Blocked user |
diff --git a/articles/_includes/_contact-sales.md b/articles/_includes/_contact-sales.md
index 5cbeffc9e2..b5a08e1e82 100644
--- a/articles/_includes/_contact-sales.md
+++ b/articles/_includes/_contact-sales.md
@@ -1,3 +1,3 @@
## More Information
-If you have specific support requirements or need more information on the Professional Services we offer, please [contact sales](https://auth0.com/?contact=true).
+If you have specific support requirements or need more information about the Professional Services we offer, please [contact Auth0 Sales](https://auth0.com/get-started?place=documentation%20post&type=link&text=contact%20auth0%20sales).
diff --git a/articles/_includes/_create_resource_server.md b/articles/_includes/_create_resource_server.md
index 95ca7cf19e..e879837b6a 100644
--- a/articles/_includes/_create_resource_server.md
+++ b/articles/_includes/_create_resource_server.md
@@ -1,10 +1,10 @@
## Create the API
-Your resource server (API) needs to be configured to verify the `access_token` and any claims contained within it. When you create a resource server in your Auth0 dashboard, it utilizes the RS256 signature method by default, meaning that Access Tokens are signed using Auth0's private key for your account. Verification is done using the corresponding public key. You can read more about the [JSON Web Key Set (JWKS)](/jwks) standard and also view the [public key](https://${account.namespace}/.well-known/jwks.json) for your Auth0 account (https://${account.namespace}/.well-known/jwks.json).
+Your resource server (API) needs to be configured to verify the Access Token and any claims contained within it. When you create a resource server in your Auth0 dashboard, it utilizes the RS256 signature method by default, meaning that Access Tokens are signed using Auth0's private key for your account. Verification is done using the corresponding public key. You can read more about the [JSON Web Key Set (JWKS)](/tokens/concepts/jwks) standard and also view the [public key(s)](https://${account.namespace}/.well-known/jwks.json) for your Auth0 account (https://${account.namespace}/.well-known/jwks.json). You can also learn how to [manage your signing keys](/tokens/guides/manage-signing-keys).
You can use any [recommended JWT library](https://jwt.io) to validate the standard claims returned in the token. The following example will demonstrate how to create a resource server API with Node. You can find more information about resource server implementations in the [Access Token documentation](https://auth0.com/docs/api-auth/config/asking-for-access-tokens).
-The `access_token` for your API must be verified against your JSON Web Key Set (JWKS) endpoint. This can be done easily with the **jwks-rsa** library available on npm.
+The Access Token for your API must be verified against your JSON Web Key Set (JWKS) endpoint. This can be done easily with the **jwks-rsa** library available on npm.
Install the dependencies.
@@ -12,7 +12,7 @@ Install the dependencies.
npm install express express-jwt jwks-rsa
```
-Create a middleware which uses **express-jwt** and **jwks-rsa** to verify the `access_token` against your JWKS endpoint.
+Create a middleware which uses **express-jwt** and **jwks-rsa** to verify the Access Token against your JWKS endpoint.
```js
const express = require('express');
@@ -21,7 +21,7 @@ const jwt = require('express-jwt');
const jwksRsa = require('jwks-rsa');
const authenticate = jwt({
- // Dynamically provide a signing key based on the kid in the header and the singing keys provided by the JWKS endpoint.
+ // Dynamically provide a signing key based on the kid in the header and the signing keys provided by the JWKS endpoint.
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
@@ -47,4 +47,4 @@ app.listen(3001);
console.log('Listening on http://localhost:3001');
```
-Note that you **must** provide the `audience` for your API. This is the identifier you set for it when you create an API in your Auth0 dashboard.
\ No newline at end of file
+Note that you **must** provide the `audience` for your API. This is the identifier you set for it when you create an API in your Auth0 dashboard.
diff --git a/articles/_includes/_deprecate-delegation.md b/articles/_includes/_deprecate-delegation.md
new file mode 100644
index 0000000000..7317d51f14
--- /dev/null
+++ b/articles/_includes/_deprecate-delegation.md
@@ -0,0 +1,3 @@
+::: warning
+By default, delegation is disabled for tenants without an add-on in use as of 8 June 2017. Legacy tenants who currently use an add-on that requires delegation may continue to use this feature. If delegation functionality is changed or removed from service at some point, customers who currently use it will be notified beforehand and given ample time to migrate.
+:::
\ No newline at end of file
diff --git a/articles/_includes/_deprecate-impersonation.md b/articles/_includes/_deprecate-impersonation.md
index 616d8c4284..4f58b1bb31 100644
--- a/articles/_includes/_deprecate-impersonation.md
+++ b/articles/_includes/_deprecate-impersonation.md
@@ -1,3 +1,3 @@
-:::warning
-Impersonation has been deprecated and will not be enabled for customers any longer. The functionality will continue to work for the customers that have it already enabled. If this changes customers will be notified beforehand and given ample time to migrate.
-:::
\ No newline at end of file
+::: warning
+Impersonation has been deprecated and will not be enabled for new customers. The functionality will continue to work for existing customers who currently have it enabled. If at some point the impersonation feature is changed or removed from service, customers who currently use it will be notified beforehand and given ample time to migrate.
+:::
diff --git a/articles/_includes/_email-domain-blacklist.md b/articles/_includes/_email-domain-blacklist.md
new file mode 100644
index 0000000000..1fdcdd1fc2
--- /dev/null
+++ b/articles/_includes/_email-domain-blacklist.md
@@ -0,0 +1,3 @@
+::: warning
+Auth0 blacklists certain "false" domains commonly used during testing. Use real email addresses to avoid disruption or `domain is blacklisted` errors.
+:::
diff --git a/articles/_includes/_embedded_login_warning.md b/articles/_includes/_embedded_login_warning.md
new file mode 100644
index 0000000000..f37d242c2d
--- /dev/null
+++ b/articles/_includes/_embedded_login_warning.md
@@ -0,0 +1,3 @@
+::: warning
+Embedded login for web uses Cross Origin Authentication. In some browsers [this can be unreliable](/cross-origin-authentication#limitations) if you do not set up a [Custom Domain](/custom-domains) **and host your app on the same domain**. Using Custom Domains with Auth0 is a paid feature. If you cannot use Custom Domains, consider [migrating to Universal Login](/guides/login/migration-embedded-universal).
+:::
\ No newline at end of file
diff --git a/articles/_includes/_enable-third-party-apps-info.md b/articles/_includes/_enable-third-party-apps-info.md
new file mode 100644
index 0000000000..e540021871
--- /dev/null
+++ b/articles/_includes/_enable-third-party-apps-info.md
@@ -0,0 +1,3 @@
+::: note
+To use this feature, you must [enable third-party applications for your Auth0 tenant](/applications/guides/enable-third-party-apps).
+:::
diff --git a/articles/_includes/_enforce-claim-namespacing.md b/articles/_includes/_enforce-claim-namespacing.md
new file mode 100644
index 0000000000..3b593d6ccf
--- /dev/null
+++ b/articles/_includes/_enforce-claim-namespacing.md
@@ -0,0 +1,5 @@
+::: warning
+By default, Auth0 always enforces namespacing; any custom claims with non-namespaced identifiers will be silently excluded from tokens.
+
+We do allow non-OIDC claims without a namespace for legacy tenants using a non-OIDC-conformant pipeline with the **Legacy User Profile** enabled, but we strongly recommend that legacy tenants migrate to an OIDC-conformant flow.
+:::
\ No newline at end of file
diff --git a/articles/_includes/_http-method.html b/articles/_includes/_http-method.html
index 42cf02bee8..cacd38d8f0 100644
--- a/articles/_includes/_http-method.html
+++ b/articles/_includes/_http-method.html
@@ -1,4 +1,4 @@
-
+
${http_method}${path}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/articles/_includes/_ip_whitelist.md b/articles/_includes/_ip_whitelist.md
new file mode 100644
index 0000000000..a3d9ad21b8
--- /dev/null
+++ b/articles/_includes/_ip_whitelist.md
@@ -0,0 +1,3 @@
+::: note Network Firewall
+If you are behind a firewall, this feature may require [whitelisting of the appropriate Auth0 IP addresses](/guides/ip-whitelist) to work properly.
+:::
diff --git a/articles/_includes/_libraries_support_frameworks.html b/articles/_includes/_libraries_support_frameworks.html
index f9a1dccec6..b14527fae5 100644
--- a/articles/_includes/_libraries_support_frameworks.html
+++ b/articles/_includes/_libraries_support_frameworks.html
@@ -23,27 +23,7 @@
diff --git a/articles/_includes/_linking_accounts.md b/articles/_includes/_linking_accounts.md
index 0ad13c36e4..547909a2a2 100644
--- a/articles/_includes/_linking_accounts.md
+++ b/articles/_includes/_linking_accounts.md
@@ -1,11 +1,11 @@
-There may be situations when your users want to log in with multiple accounts that they own. In these cases, you may want to link these accounts together so that they are all reflected in the user's Auth0 profile. For example, if a user has signed up with an email and password (which provides very little information about them), you can ask them to link their account to an OAuth provider like Facebook or Google to gain access to their social profile. For a detailed description of linking accounts, see the [full documentation](https://auth0.com/docs/link-accounts).
+There may be situations when your users want to log in with multiple accounts that they own. In these cases, you may want to link these accounts together so that they are all reflected in the user's Auth0 profile. For example, if a user has signed up with an email and password (which provides very little information about them), you can ask them to link their account to an OAuth provider like Facebook or Google to gain access to their social profile. See [User Account Linking](/users/concepts/overview-user-account-linking) for details.
## Linking Accounts
-To link accounts, call the [link a user account](/api/management/v2#!/Users/post_identities) endpoint. You will need the `id_token` and `user_id` of the primary account and the `id_token` of the secondary account.
+To link accounts, call the [link a user account](/api/management/v2#!/Users/post_identities) endpoint. You will need the ID Token and `user_id` of the primary account and the ID Token of the secondary account.
-To differentiate the login from the linking login, you will need to create a second instance of `Auth0Lock` to obtain the `id_token` of the secondary account.
+To differentiate the login from the linking login, you will need to create a second instance of `Auth0Lock` to obtain the ID Token of the secondary account.
Since all instances of `Auth0Lock` will receive the `authenticated` event, you will need a way to determine if authentication came from the primary login or the linking login.
-You can use the `auth.params` property of the [options object](https://github.com/auth0/lock#authentication-options) of `Auth0Lock` to add a `state` property with the value `'linking'`.
\ No newline at end of file
+You can use the `auth.params` property of the [options object](https://github.com/auth0/lock#authentication-options) of `Auth0Lock` to add a `state` property with the value `'linking'`.
diff --git a/articles/_includes/_lock_auth0js_deprecations_notice.md b/articles/_includes/_lock_auth0js_deprecations_notice.md
index f989f7af01..9e03f9bb98 100644
--- a/articles/_includes/_lock_auth0js_deprecations_notice.md
+++ b/articles/_includes/_lock_auth0js_deprecations_notice.md
@@ -1,3 +1,3 @@
::: panel-warning Lock and Auth0.js Deprecations
-The Lock v8, v9, and v10 widgets as well as the Auth0.js v6, v7, and v8 SDKs are deprecated and should be migrated away from prior to their removal from service on July 16, 2018. The [Deprecation Guidance](/migrations/guides/legacy-lock-api-deprecation) page provides details about update recommendations.
+The Lock v8, v9, and v10 widgets as well as the Auth0.js v6, v7, and v8 SDKs are deprecated and should be migrated away from prior to their removal from service on July 16, 2018.
:::
\ No newline at end of file
diff --git a/articles/_includes/_login_auth0_hosted_login_page.md b/articles/_includes/_login_auth0_hosted_login_page.md
index f4b21646f3..78c16d5875 100644
--- a/articles/_includes/_login_auth0_hosted_login_page.md
+++ b/articles/_includes/_login_auth0_hosted_login_page.md
@@ -1 +1 @@
-Auth0's [universal login](/hosted-pages/login) is the easiest way to set up authentication in your application.
\ No newline at end of file
+Auth0's [Universal Login](/hosted-pages/login) is the easiest way to set up authentication in your application.
diff --git a/articles/_includes/_logout_url.md b/articles/_includes/_logout_url.md
new file mode 100644
index 0000000000..ed3e9ac189
--- /dev/null
+++ b/articles/_includes/_logout_url.md
@@ -0,0 +1,11 @@
+
+
+### Configure Logout URLs
+
+A logout URL is a URL in your application that Auth0 can return to after the user has been logged out of the authorization server. This is specified in the `returnTo` query parameter. The logout URL for your app must be added to the **Allowed Logout URLs** field in your Application Settings. If this field is not set, users will be unable to log out from the application and will get an error.
+
+<% if (typeof(returnTo) !== "undefined") { %>
+ ::: note
+ If you are following along with the sample project you downloaded from the top of this page, the logout URL you need to add to the **Allowed Logout URLs** field is `${returnTo}`.
+ :::
+<% } %>
diff --git a/articles/_includes/_metadata_on_signup_warning.md b/articles/_includes/_metadata_on_signup_warning.md
new file mode 100644
index 0000000000..1af9aab000
--- /dev/null
+++ b/articles/_includes/_metadata_on_signup_warning.md
@@ -0,0 +1,3 @@
+::: note
+When setting the `user_metadata` field using the Authentication API's [Signup endpoint](/api/authentication?javascript#signup), you are limited to a maximum of 10 `String` fields and 500 characters.
+:::
diff --git a/articles/_includes/_native_passwordless_warning.md b/articles/_includes/_native_passwordless_warning.md
index 1465cf3fa5..04eaae8300 100644
--- a/articles/_includes/_native_passwordless_warning.md
+++ b/articles/_includes/_native_passwordless_warning.md
@@ -1,3 +1,3 @@
::: warning
-Passwordless functionality should not be embedded in native apps until Auth0 libraries can be updated to properly support it. Until that time, passwordless authentication can still be achieved by using [universal login](/connections/passwordless/native-passwordless-universal) via the web.
+This functionality has been deprecated in native. After June 2017, tenants cannot use the native passwordless flow. The functionality will continue to work for tenants that currently have it enabled. If at some point the passwordless mode feature is changed or removed from service, customers who currently use it will be notified beforehand and given ample time to migrate.
:::
diff --git a/articles/_includes/_new_api.html b/articles/_includes/_new_api.html
index 5ef9d7f6ff..924a36341f 100644
--- a/articles/_includes/_new_api.html
+++ b/articles/_includes/_new_api.html
@@ -1,5 +1,5 @@
<% if (account.userName) { %>
-
In the APIs section in dashboard, click the Create API button. Provide a Name and Identifier for your API. You must choose the RS256 signing algorithm. Once it is created, navigate to the Scopes tab and create the applicable scopes for your API.
+
In the APIs section in dashboard, click the Create API button. Provide a Name and Identifier for your API. You must choose the RS256 signing algorithm. Once it is created, navigate to the Scopes tab and create the applicable scopes for your API.
<% } else { %>
-
Create an Auth0 account (or login) navigate to the APIs section in Dashboard. Click the Create API button and provide a Name and Identifier for your API. You must choose the RS256 signing algorithm. Once it is created, navigate to the Scopes tab and create the applicable scopes for your API.
+
Create an Auth0 account (or login) navigate to the APIs section in Dashboard. Click the Create API button and provide a Name and Identifier for your API. You must choose the RS256 signing algorithm. Once it is created, navigate to the Scopes tab and create the applicable scopes for your API.
<% } %>
\ No newline at end of file
diff --git a/articles/_includes/_new_app.md b/articles/_includes/_new_app.md
index 16b5983caf..4d390027eb 100644
--- a/articles/_includes/_new_app.md
+++ b/articles/_includes/_new_app.md
@@ -1,20 +1,28 @@
-## Get Your Application Keys
+## Configure Auth0
+### Get Your Application Keys
-<% if (!account.userName) { %>
-The first step for integrating Auth0 in your app is to create an [account](${manage_url}/login). When you sign up for Auth0, you will be invited to create a new application.
+When you signed up for Auth0, a new application was created for you, or you could have created a new one. You will need some details about that application to communicate with Auth0. You can get these details from the Application Settings section in the Auth0 dashboard.
-<% } else { %>
-When you signed up for Auth0, you created a new application.
+<% if(typeof hideDashboardScreenshot === 'undefined' || hideDashboardScreenshot !== true) { %>
+
+<% } %>
+<% if(typeof isPublicClient === 'undefined' || isPublicClient === true) { %>
+::: note
+When using the Default App with a Native or Single Page Application, ensure to update the **Token Endpoint Authentication Method** to `None` and set the **Application Type** to either `SPA` or `Native`.
+:::
<% } %>
-You will need some details about this application to communicate with Auth0. You can get them from the [Application Settings](${manage_url}/#/applications/${account.clientId}/settings) in the Auth0 dashboard.
-
+
You need the following information:
-* **Client ID**
+
* **Domain**
+* **Client ID**
+<% if(typeof showClientSecret !== 'undefined' && showClientSecret === true) { %>
+* **Client Secret**
+<% } %>
+<% if(typeof hideDownloadSample === 'undefined' || hideDownloadSample !== true) { %>
::: note
-If you download the sample from the top of this page, these details are filled out for you. If you have more than one application in your account, the sample comes with the values for your **Default App**.
+If you download the sample from the top of this page, these details are filled out for you.
:::
-
-
+<% } %>
diff --git a/articles/_includes/_parental-consent.md b/articles/_includes/_parental-consent.md
new file mode 100644
index 0000000000..eaa0337c61
--- /dev/null
+++ b/articles/_includes/_parental-consent.md
@@ -0,0 +1,3 @@
+::: note
+If you require a specialized consent prompt, for example a parental consent, you need to build your own custom consent form. Be aware that laws vary according to country.
+:::
\ No newline at end of file
diff --git a/articles/_includes/_rbac_methods.md b/articles/_includes/_rbac_methods.md
new file mode 100644
index 0000000000..57feb5baa3
--- /dev/null
+++ b/articles/_includes/_rbac_methods.md
@@ -0,0 +1,8 @@
+Currently, we provide two ways of implementing [role-based access control (RBAC)](/authorization/concepts/rbac), which you can use in place of or in combination with your API's own internal access control system:
+
+* [Authorization Core](/authorization/guides/how-to)
+* [Authorization Extension](/extensions/authorization-extension)
+
+We are expanding our Authorization Core feature set to match the functionality of the Authorization Extension. Our new core RBAC implementation improves performance and scalability and will eventually provide a more flexible RBAC system than the Authorization Extension.
+
+For now, both implement the key features of RBAC and allow you to restrict the custom scopes defined for an API to those that have been assigned to the user as permissions. For a comparison, see [Authorization Core vs. Authorization Extension](/authorization/concepts/core-vs-extension).
\ No newline at end of file
diff --git a/articles/_includes/_rbac_vs_extensions.md b/articles/_includes/_rbac_vs_extensions.md
new file mode 100644
index 0000000000..58e7c0af76
--- /dev/null
+++ b/articles/_includes/_rbac_vs_extensions.md
@@ -0,0 +1,5 @@
+::: warning
+The [Authorization Core](/authorization/guides/how-to) feature set and [Authorization Extension](/extensions/authorization-extension) are completely separate features. To manage groups, roles, or permissions, you will need to use the feature they were originally created in.
+
+Although the [Delegated Administration Extension](/extensions/delegated-admin) and the [Authorization Core](/authorization/guides/how-to) feature set are completely separate features, you can use the Authorization Core feature set to create and manage roles for the DAE if you use a rule. To learn how, see [Sample Use Cases: Rules with Authorization](/authorization/concepts/sample-use-cases-rules#manage-delegated-administration-extension-roles-using-the-authorization-core-feature-set).
+:::
\ No newline at end of file
diff --git a/articles/_includes/_refresh_token_rotation_panel.md b/articles/_includes/_refresh_token_rotation_panel.md
new file mode 100644
index 0000000000..bb3221d0ff
--- /dev/null
+++ b/articles/_includes/_refresh_token_rotation_panel.md
@@ -0,0 +1,3 @@
+::: note
+If you have [Refresh Token Rotation](/tokens/concepts/refresh-token-rotation) enabled, a new Refresh Token is generated with each request and issued along with the Access Token. When a Refresh Token is exchanged, the previous Refresh Token is invalidated but information about the relationship is retained by the authorization server.
+:::
diff --git a/articles/_includes/_refresh_token_rotation_recommended.md b/articles/_includes/_refresh_token_rotation_recommended.md
new file mode 100644
index 0000000000..5f52feeac1
--- /dev/null
+++ b/articles/_includes/_refresh_token_rotation_recommended.md
@@ -0,0 +1,3 @@
+::: panel Refresh Token Rotation
+Recent advancements in user privacy controls in browsers adversely impact the user experience by preventing access to third-party cookies. Auth0 recommends using [Refresh Token Rotation](/tokens/concepts/refresh-token-rotation), which provides a secure method for using refresh tokens in SPAs while providing end-users with seamless access to resources without the disruption in UX caused by browser privacy technology like ITP.
+:::
diff --git a/articles/_includes/_samesite_none.md b/articles/_includes/_samesite_none.md
new file mode 100644
index 0000000000..9449a343c0
--- /dev/null
+++ b/articles/_includes/_samesite_none.md
@@ -0,0 +1,10 @@
+::: note
+Previously in Auth0, the [`samesite` cookie attribute](/sessions/concepts/cookie-attributes) options were `true`, `false`, `strict` or `lax`. If you didn't set the attribute manually, Auth0 would use the default value of `false`.
+
+Effective February 2020, Google Chrome v80 will change the way it handles cookies. To that end, Auth0 plans on implementing the following changes to how it handles cookies:
+
+* Cookies without the `samesite` attribute set will be set to `lax`
+* Cookies with `sameSite=none` must be secured, otherwise they cannot be saved in the browser's cookie jar
+
+The goal of these changes are to improve security and help mitigate CSRF attacks.
+:::
diff --git a/articles/_includes/_test-this-endpoint.md b/articles/_includes/_test-this-endpoint.md
index a6c6a1ff29..e2d873ea5d 100644
--- a/articles/_includes/_test-this-endpoint.md
+++ b/articles/_includes/_test-this-endpoint.md
@@ -1,5 +1,4 @@
-You can use our **Authentication API Debugger** extension to test this endpoint. In order to do so you need to be logged in and have installed the [Authentication API Debugger extension](/extensions/authentication-api-debugger).
-
+
Click on **Install Debugger** to go to the article that explains how (you only have to do this once).
<%
diff --git a/articles/_includes/_token_signature.md b/articles/_includes/_token_signature.md
new file mode 100644
index 0000000000..6af09f7685
--- /dev/null
+++ b/articles/_includes/_token_signature.md
@@ -0,0 +1,9 @@
+
+
+### Verify JWT Token Signature setting
+
+JSON Web Tokens (JWTs) should be signed using the RS256 signing algorithm where possible, as it provides [enhanced security over HS256](https://auth0.com/docs/tokens/concepts/signing-algorithms#our-recommendation).
+
+RS256 is the default, but if you are [running into errors](https://auth0.com/docs/errors/libraries/auth0-js/invalid-token#parsing-an-hs256-signed-id-token-without-an-access-token) you can verify your settings by clicking on **Show Advanced Settings** at the bottom of your Auth0 Application settings screen in the dashboard. Click the **OAuth** tab to show the signature algorithm configuration. **JsonWebToken Signature Algorithm** should be set to **RS256**, and the **OIDC Conformant** setting should be enabled.
+
+
diff --git a/articles/_includes/_users_update_normalized_profile_attributes.md b/articles/_includes/_users_update_normalized_profile_attributes.md
new file mode 100644
index 0000000000..822a2e3d50
--- /dev/null
+++ b/articles/_includes/_users_update_normalized_profile_attributes.md
@@ -0,0 +1,3 @@
+By default, user profile attributes provided by identity providers other than Auth0 (such as Google, Facebook, Twitter) are not directly editable because they are updated from the identity provider each time the user logs in.
+
+To be able to edit the `name`, `nickname`, `given_name`, `family_name`, or `picture` root attributes on the normalized user profile, you must [configure your connection sync with Auth0](/dashboard/guides/connections/configure-connection-sync) so that user attributes will be updated from the identity provider only on user profile creation. These root attributes will then be available to be [edited individually](/api/management/guides/users/update-root-attributes-users) or [by bulk import](/api/management/guides/users/set-root-attributes-user-import) using the Management API.
diff --git a/articles/_includes/_uses-delegation.md b/articles/_includes/_uses-delegation.md
new file mode 100644
index 0000000000..2a157656f4
--- /dev/null
+++ b/articles/_includes/_uses-delegation.md
@@ -0,0 +1,3 @@
+::: warning
+This feature uses delegation. By default, delegation is disabled for tenants without an add-on in use as of 8 June 2017. Legacy tenants who currently use an add-on that requires delegation may continue to use this feature. If delegation functionality is changed or removed from service at some point, customers who currently use it will be notified beforehand and given ample time to migrate. In addition, note that delegation does not support the use of custom domains so any features depending on it may not be fully functional alongside a custom domain.
+:::
diff --git a/articles/_includes/_version_warning_api.md b/articles/_includes/_version_warning_api.md
new file mode 100644
index 0000000000..bf86f5773c
--- /dev/null
+++ b/articles/_includes/_version_warning_api.md
@@ -0,0 +1,3 @@
+::: warning
+This version of the Management API has been deprecated. We recommend that you use the [new version](/api/management/v2) instead. Please refer to the [Migration Guide](/migrations/guides/management-api-v1-v2) for more information.
+:::
diff --git a/articles/_includes/_version_warning_auth0js.md b/articles/_includes/_version_warning_auth0js.md
index e8dab61d10..3c6104e535 100644
--- a/articles/_includes/_version_warning_auth0js.md
+++ b/articles/_includes/_version_warning_auth0js.md
@@ -1,3 +1,3 @@
::: version-warning
-This document covers a deprecated version of Auth0.js. We recommend that you [migrate to Auth0.js v9](/libraries/auth0js/v9/migration-guide) as soon as possible.
+This document covers a deprecated version of Auth0.js which uses endpoints that have been removed from service. It will no longer function as expected. We recommend that you [migrate to Auth0.js v9](/libraries/auth0js/v9/migration-guide) as soon as possible.
:::
\ No newline at end of file
diff --git a/articles/_includes/_version_warning_lock.md b/articles/_includes/_version_warning_lock.md
index ed25f1ef8c..707490b682 100644
--- a/articles/_includes/_version_warning_lock.md
+++ b/articles/_includes/_version_warning_lock.md
@@ -1,3 +1,3 @@
::: version-warning
-This document covers a deprecated version of Lock. We recommend that you [migrate to Lock v11](/libraries/lock/v11/migration-guide) as soon as possible.
+This document covers a deprecated version of Lock which uses endpoints that have been removed from service. It will no longer function as expected. We recommend that you migrate to Lock v11 as soon as possible.
:::
\ No newline at end of file
diff --git a/articles/_includes/_web_origins.md b/articles/_includes/_web_origins.md
new file mode 100644
index 0000000000..27ba7150f1
--- /dev/null
+++ b/articles/_includes/_web_origins.md
@@ -0,0 +1,5 @@
+
+
+### Configure Allowed Web Origins
+
+You need to add the URL for your app to the **Allowed Web Origins** field in your Application Settings. If you don't register your application URL here, the application will be unable to silently refresh the authentication tokens and your users will be logged out the next time they visit the application, or refresh the page.
\ No newline at end of file
diff --git a/articles/_includes/_webtask.md b/articles/_includes/_webtask.md
new file mode 100644
index 0000000000..71356fc124
--- /dev/null
+++ b/articles/_includes/_webtask.md
@@ -0,0 +1,3 @@
+::: warning
+Only tenants created prior to 17 July 2018 have access to Webtask.io and the Webtask CLI. If you are an enterprise customer with a newer tenant, please contact your account representative to request access. Other requests can be made through the [Auth0 Contact Form](https://auth0.com/get-started?place=documentation%20post&type=link&text=auth0%20contact%20form) and will be evaluated on a case-by-case basis.
+:::
diff --git a/articles/addons/azure-blob-storage.md b/articles/addons/azure-blob-storage.md
index 87b5cd1634..fa945a5c8b 100644
--- a/articles/addons/azure-blob-storage.md
+++ b/articles/addons/azure-blob-storage.md
@@ -1,21 +1,29 @@
---
addon: Azure Blob Storage
+title: Azure Blob Storage Add-on
thirdParty: true
+public: false
url: /addons/azure-blob-storage
alias:
- azure blob storage
- azblob
image: /media/platforms/azure.png
-tags:
+topics:
- quickstart
+ - azure
+ - addons
articles:
- authenticate
-description: This tutorial will show you how to use the Auth0 to authenticate and authorize Azure Blob Storage.
+contentType: how-to
+description: Learn how to use Auth0 to authenticate and authorize Azure Blob Storage.
+useCase: integrate-third-party-apps
---
-# Azure Blob Storage Addon
+# Azure Blob Storage Add-on
-Here's a sample call to the delegation endpoint to get the SAS:
+<%= include('../_includes/_uses-delegation') %>
+
+Here's a sample call to the delegation endpoint to get the Shared Access Signature (SAS):
```text
POST https://${account.namespace}/delegation
@@ -43,7 +51,7 @@ The result of calling the delegation endpoint will be something like:
}
```
-You can use the blob SAS token either by appending it to a url directly or by passing it to one of the Azure Storage SDKs.
+You can use the blob SAS token either by appending it to a URL directly or by passing it to one of the Azure Storage SDKs.
```text
GET https://{STORAGEACCOUNT}.blob.core.windows.net/mycontainer/myblob.txt?st=2015-01-08T18%3A45%3A14Z&se=2015-01-08T18%3A50%3A14Z&sp=r&sv=2014-02-14&sr=b&sig=13ABC456...
diff --git a/articles/addons/azure-mobile-services.md b/articles/addons/azure-mobile-services.md
index 3e5f8dbbf0..2d88dd226a 100644
--- a/articles/addons/azure-mobile-services.md
+++ b/articles/addons/azure-mobile-services.md
@@ -1,6 +1,8 @@
---
-addon: Azure Mobile Services
+addon: Windows Azure Mobile Services
+title: Windows Azure Mobile Services Add-on
thirdParty: true
+public: false
url: /addons/azure-mobile-services
image: /media/platforms/azure.png
snippets:
@@ -12,14 +14,28 @@ alias:
- windows-azure-vm
- azure-websites
- azure-vm
-description: This tutorial will show you how to use the Auth0 to authenticate and authorize Azure Mobile Services.
+topics:
+ - azure
+ - mobile
+ - addons
+contentType: how-to
+useCase: integrate-third-party-apps
+description: Learn how to use Auth0 to authenticate and authorize Windows Azure Mobile Services (WAMS).
---
-# Azure Mobile Services Addon
+# Windows Azure Mobile Services Add-on
+
+<%= include('../_includes/_uses-delegation') %>
## 1. Create an application
-WAMS endpoints can be used from anywhere. For example: [Android](/native-platforms/android), [iOS](/native-platforms/ios-objc), [Windows UWP C#](/native-platforms/windows-uwp-csharp), [JavaScript](/application-platforms/vanillajs) or [Windows Phone](/native-platforms/windowsphone). You can use any of these tutorials for configuring an app that interacts with WAMS.
+Windows Azure Mobile Services (WAMS) endpoints can be used from anywhere. To configure an app that interacts with WAMS, you can use any of the following tutorials:
+
+- [Android](/quickstart/native/android)
+- [iOS](/quickstart/native/ios-objc)
+- [Windows UWP C#](/quickstart/native/windows-uwp-csharp)
+- [JavaScript](/quickstart/spa/vanillajs)
+- [Windows Phone](/quickstart/native/wpf-winforms)
The samples that you can download from the Azure Portal are a good starting point.
@@ -37,7 +53,7 @@ The important aspects of these lines are:
1. The `Auth0Client` class takes 2 parameters: your `namespace` and the `clientId` of the application.
2. There are various overloads for the `LoginAsync` method. In the example above, all options will be presented to the user. You can use other versions of `LoginAsync` to direct login to a specific provider. For example: `LoginAsync("github")` will have users login exclusively with GitHub.
-3. The `GetDelegationToken` call exchanges the application token (received in step #2) for another token to be used for with WAMS.
+3. The `GetDelegationToken` call exchanges the application token (received in step #2) for another token to be used with WAMS.
4. The input for the `GetDelegationToken` method is the `clientID` of your WAMS enabled app.
5. A new `MobileServiceUser` object is created with the new information.
@@ -45,7 +61,7 @@ The `GetDelegationToken` call allows your app to interact with multiple WAMS API
For example, you can login a user with GitHub, then connect them to WAMS and also interact with an AWS hosted endpoint. The delegation call allows you to flow the identity of the user securely across multiple environments.
-## 3. Using the user identity in the WAMS backend
+## 3. Use the user identity in the WAMS backend
The final step is to use the information in the token in the server code. Most likely you will have to do the following two things:
diff --git a/articles/addons/azure-sb.md b/articles/addons/azure-sb.md
index b2f233a130..da89208289 100644
--- a/articles/addons/azure-sb.md
+++ b/articles/addons/azure-sb.md
@@ -1,20 +1,28 @@
---
addon: Azure Service Bus
+title: Azure Service Bus Add-on
thirdParty: true
+public: false
url: /addons/azure-sb
alias:
- Azure Service Bus
image: /media/platforms/azure.png
-tags:
+topics:
- quickstart
+ - azure
+ - addons
articles:
- authenticate
-description: This tutorial will show you how to use the Auth0 to authenticate and authorize Azure Service Bus.
+contentType: how-to
+useCase: integrate-third-party-apps
+description: Learn how to use Auth0 to authenticate and authorize Azure Service Bus.
---
-# Azure Service Bus Addon
+# Azure Service Bus Add-on
-Here's a sample call to the delegation endpoint to get the SAS:
+<%= include('../_includes/_uses-delegation') %>
+
+Here's a sample call to the delegation endpoint to get the Shared Access Signature (SAS):
```text
POST https://${account.namespace}/delegation
diff --git a/articles/addons/index.md b/articles/addons/index.md
index 2e30ba35c6..bd86928457 100644
--- a/articles/addons/index.md
+++ b/articles/addons/index.md
@@ -1,26 +1,48 @@
---
url: /addons
-description: How to setup Application Addons, like Amazon Web Services and Azure Blob Storage, with your Auth0 app.
+title: Add-ons
+description: Learn about add-ons and how they are related to Auth0-registered Applications.
+public: false
+topics:
+ - applications
+ - add-ons
+contentType:
+ - concept
+ - index
+useCase:
+ - build-an-app
+ - integrate-third-party-apps
---
-# Auth0 Application Addons
+# Add-ons
-Addons are plugins associated with an Application in Auth0. Usually, they are 3rd party APIs used by the application that Auth0 generates Access Tokens for (such as Salesforce, Azure Service Bus, Azure Mobile Services, SAP, and so on).
+<%= include('../_includes/_uses-delegation') %>
-## How to configure an Addon
+Add-ons are plugins associated with an application registered with Auth0. Usually, they are third-party APIs used by application(s) for which Auth0 generates Access Tokens (e.g., Salesforce, Azure Service Bus, Windows Azure Mobile Services, SAP).
-Go to [Dashboard > Applications > Settings > Addons](${manage_url}/#/applications/${account.clientId}/addons) page and use the toggle to enable the add-on you want to configure.
+Some typical scenarios for using add-ons include:
-
+* **Accessing External APIs**: Using the Delegation endpoint, you can exchange your application's Access Token for a third-party service's (e.g., Salesforce, Amazon) Access Token.
-Each integration is different and requires different parameters and configuration. Once the addon is activated, you will see tailored instructions with details on how to integrate with it in the dashboard.
+* **Integrating with Applications using SAML2/WS-Federation**: Since Add-ons allow you to configure every aspect of the SAML2/WS-Federation integration, they allow you to integrate with any custom or Single Sign-on (SSO) integration that does not currently enjoy built-in Auth0 support.
-## Additional information for specific Addons
+
-- Amazon Web Services: For more info on how to use delegation with the AWS API Gateway, see the [AWS API Gateway](/integrations/aws-api-gateway/delegation) Tutorial
-- [Azure Blob Storage](/addons/azure-blob-storage)
-- [Azure Mobile Services](/addons/azure-mobile-services)
-- [Azure Service Bus](/addons/azure-sb)
-- [Salesforce (sandbox)](/addons/salesforce-sandbox)
-- [Salesforce](/addons/salesforce)
-- [SAP OData](/addons/sap-odata)
+## Available Add-ons
+
+- Amazon Web Services
+- Firebase
+- Layer
+- Salesforce
+- Salesforce (Sandbox)
+- SAP
+- Azure Mobile Services
+- Azure Service Bus
+- Azure Blob Storage
+- SAML2
+- WS-Fed
+
+## Keep reading
+
+- [View Add-ons](/dashboard/guides/applications/view-addons)
+- [Set Up Add-Ons](/dashboard/guides/applications/set-up-addons)
\ No newline at end of file
diff --git a/articles/addons/salesforce-sandbox.md b/articles/addons/salesforce-sandbox.md
index b6a21106ce..79bd815fe1 100644
--- a/articles/addons/salesforce-sandbox.md
+++ b/articles/addons/salesforce-sandbox.md
@@ -1,19 +1,28 @@
---
addon: Salesforce (sandbox)
+title: Salesforce (Sandbox) Add-on
thirdParty: true
+public: false
url: /addons/salesforce-sandbox
alias:
- salesforce
image: /media/addons/salesforce_sandbox_api.svg
-description: This tutorial will show you how to use the Auth0 to authenticate and authorize your Salesforce (Sandbox) services.
+description: Learn how to use Auth0 to authenticate and authorize your Salesforce (Sandbox) services.
+topics:
+ - salesforce
+ - addons
+useCase: integrate-third-party-apps
+contentType: how-to
---
-# Salesforce (Sandbox) Addon
+# Salesforce (Sandbox) Add-on
+
+<%= include('../_includes/_uses-delegation') %>
-Auth0 supports both the __production__ connection to Salesforce and the __Sandbox__, the only difference being the endpoints hosted by Salesforce: `https://login.salesforce.com` and `https://test.salesforce.com` respectively.
+Auth0 supports both the __production__ connection to Salesforce and the __Sandbox__, the only difference being the endpoints hosted by Salesforce: `https://login.salesforce.com` and `https://test.salesforce.com`, respectively.
::: note
- Under the hood, Auth0 uses OAuth 2.0 JWT Bearer Token Flow to obtain an access_token. All details of construction of the right JWT are taken care of by Auth0.
+ Under the hood, Auth0 uses OAuth 2.0 JWT Bearer Token Flow to obtain an Access Token. All details of construction of the right JWT are taken care of by Auth0.
:::

diff --git a/articles/addons/salesforce.md b/articles/addons/salesforce.md
index 4ecd389fa9..54aa6bb93e 100644
--- a/articles/addons/salesforce.md
+++ b/articles/addons/salesforce.md
@@ -1,16 +1,25 @@
---
addon: Salesforce
+title: Salesforce Add-on
alias:
- salesforce
url: addons/salesforce
thirdParty: true
+public: false
image: /media/addons/salesforce.svg
-description: This tutorial will show you how to use the Auth0 to authenticate and authorize your Salesforce services.
+description: Learn how to use Auth0 to authenticate and authorize your Salesforce services.
+topics:
+ - salesforce
+ - addons
+useCase: integrate-third-party-apps
+contentType: how-to
---
-# Salesforce Addon
+# Salesforce Add-on
+
+<%= include('../_includes/_uses-delegation') %>
-Auth0 supports both the __production__ connection to Salesforce and the __Sandbox__, the only difference being the endpoints hosted by Salesforce: `https://login.salesforce.com` and `https://test.salesforce.com` respectively.
+Auth0 supports both the __production__ connection to Salesforce and the __Sandbox__, the only difference being the endpoints hosted by Salesforce: `https://login.salesforce.com` and `https://test.salesforce.com`, respectively.
The integration also supports getting tokens for __Salesforce Community Sites__. For this to work, you need to pass two additional parameters:
@@ -23,7 +32,7 @@ community_url_section: 'members'
```
::: note
- Under the hood, Auth0 uses OAuth 2.0 JWT Bearer Token Flow to obtain an access_token. All details of construction of the right JWT are taken care of by Auth0.
+ Under the hood, Auth0 uses OAuth 2.0 JWT Bearer Token Flow to obtain an Access Token. All details of construction of the right JWT are taken care of by Auth0.
:::

diff --git a/articles/addons/sap-odata.md b/articles/addons/sap-odata.md
index b86909de42..4c5db1bcce 100644
--- a/articles/addons/sap-odata.md
+++ b/articles/addons/sap-odata.md
@@ -1,20 +1,30 @@
---
addon: SAP OData
+title: SAP OData Add-on
alias:
- sap
url: /addons/sap-odata
image: /media/addons/sap_api.svg
-description: This tutorial will show you how to use the Auth0 to authenticate and authorize your SAP OData services.
+description: Learn how to use Auth0 to authenticate and authorize your SAP OData services.
+public: false
+topics:
+ - sap
+ - addons
+ - odata
+useCase: integrate-third-party-apps
+contentType: how-to
---
-# SAP OData Addon
+# SAP OData Add-on
+
+<%= include('../_includes/_uses-delegation') %>
::: warning
This integration is in experimental mode. Contact us if you have questions.
:::
::: note
- Under the hood, Auth0 uses SAML 2.0 Bearer Assertion Flow for OAuth 2.0 to obtain an access_token. All details of construction of the right SAML token are taken care of by Auth0.
+ Under the hood, Auth0 uses SAML 2.0 Bearer Assertion Flow for OAuth 2.0 to obtain an Access Token. All details of construction of the right SAML token are taken care of by Auth0.
:::

diff --git a/articles/analytics/_includes/_install.md b/articles/analytics/_includes/_install.md
new file mode 100755
index 0000000000..4e86feb323
--- /dev/null
+++ b/articles/analytics/_includes/_install.md
@@ -0,0 +1,20 @@
+## Install
+
+To add the <%- name %> integration to your app, include a reference to the `Auth0 Analytics.js` script on any pages with Auth0 Lock. Include the script reference **after**** Lock *and* set the configuration options before the script reference.
+
+```
+
+
+
+```
+
+::: note
+The script version above uses a placeholder version `X.Y.Z`. For example, to reference release, 1.3.1 use `https://cdn.auth0.com/js/analytics/1.3.1/analytics.min.js`. You can [find the latest release's version number](https://github.com/auth0/auth0-analytics.js/releases/) on GitHub.
+:::
diff --git a/articles/analytics/_includes/_usage.md b/articles/analytics/_includes/_usage.md
new file mode 100755
index 0000000000..9d4a7485c2
--- /dev/null
+++ b/articles/analytics/_includes/_usage.md
@@ -0,0 +1,20 @@
+## Usage
+
+After installation on your site, you will start collecting data. Auth0 Analytics will immediately begin sending events to <%- name %>.
+
+You will see the following events being logged:
+
+* Auth0 Lock show
+* Auth0 Lock hide
+* Auth0 Lock unrecoverable_error
+* Auth0 Lock authenticated
+* Auth0 Lock authorization_error
+* Auth0 Lock forgot_password ready
+* Auth0 Lock forgot_password submit
+* Auth0 Lock signin submit
+* Auth0 Lock signup submit
+* Auth0 Lock federated login
+
+Note that some events that Lock emits like `hash_parsed` are not used for analytics purposes. Also, be aware that some events are only available in newer versions of Lock. If you are using an older version of Lock you will only see some of these events. We suggest upgrading to the latest version of Lock to get the most of the Auth0 Analytics integration.
+
+For more information on the events that are sent see the [Lock API documentation](/libraries/lock/v11/api#on-).
diff --git a/articles/analytics/guides/facebook-analytics.md b/articles/analytics/guides/facebook-analytics.md
new file mode 100644
index 0000000000..bc4093476f
--- /dev/null
+++ b/articles/analytics/guides/facebook-analytics.md
@@ -0,0 +1,69 @@
+---
+description: Learn how to install and configure the Facebook Analytics for Auth0 integration.
+topics:
+ - facebook
+ - analytics
+public: false
+contentType: how-to
+useCase:
+ - manage-analytics
+ - analyze-external-analytics
+---
+# Integrate Facebook Analytics with Auth0
+
+Install and configure the **Facebook Analytics for Auth0** integration on your own page that is using [Lock](/libraries/lock) or the [hosted Lock pages](/universal-login). You can configure funnels and reports inside of Facebook Analytics to get the most out of this integration.
+
+<%= include('../_includes/_install', { name: "Facebook Analytics" }) %>
+
+## Setup
+
+If you already have either the Facebook Tracking Pixel or the Facebook Javascript SDK referenced on your site, configure Auth0 Analytics with the `preload` option as shown below. If you don't have either script loaded you need to set your Facebook Analytics App ID using the Facebook Javascript SDK configuration below.
+
+We recommend [creating funnels](https://www.facebook.com/help/analytics/935921203105136) to measure the success of your acquisition and registration flows using these new events.
+
+### Configure Facebook Javascript SDK (Recommended)
+
+The simplest configuration is to let the Analytics script load the Facebook Javascript SDK. You can do this by providing your Facebook Analytics App ID to the analytics options as shown below.
+
+```
+
+```
+
+If you have already loaded the Facebook Javascript SDK on your site, configure Auth0 Analytics to not load it again as shown below.
+
+```
+
+```
+
+### Configure Facebook Pixel
+
+If you already have the Facebook Pixel installed on your site you can use that configuration mode. Note that with the Facebook Pixel, certain features of Facebook Analytics are not available. The configuration for using the pixel is shown below.
+
+```
+
+```
+
+<%= include('../_includes/_usage', { name: "Facebook Analytics" }) %>
+
+## Keep reading
+
+[Facebook Analytics documentation](https://www.facebook.com/help/analytics/1710582659188030)
+
diff --git a/articles/analytics/guides/google-analytics.md b/articles/analytics/guides/google-analytics.md
new file mode 100644
index 0000000000..4367921202
--- /dev/null
+++ b/articles/analytics/guides/google-analytics.md
@@ -0,0 +1,46 @@
+---
+description: Learn how to install and configure the Google Analytics for Auth0 integration.
+topics:
+ - google
+ - analytics
+public: false
+contentType: how-to
+useCase:
+ - manage-analytics
+ - analyze-external-analytics
+---
+# Integrate Google Analytics with Auth0
+
+This article explains how to install and configure the **Google Analytics for Auth0** integration. You can use this integration on your own page that is using Lock. You can configure funnels and reports inside of Google Analytics to get the most out of this integration.
+
+## Setup
+
+1. Set analytics configuration options *before* you include the references to the Lock and Auth0 Analytics libraries.
+
+ ```javascript
+
+ ```
+
+2. Include the script reference to the `auth0-analytics.js`. This needs to be included *after* the call to Lock.
+
+ ```javascript
+
+
+ ```
+
+::: note
+The script version above uses a placeholder version `X.Y.Z`. For example, to reference release 1.3.1 use `https://cdn.auth0.com/js/analytics/1.3.1/analytics.min.js`. You can [find the latest release's version number](https://github.com/auth0/auth0-analytics.js/releases/) on GitHub.
+:::
+
+<%= include('../_includes/_usage', { name: "Google Analytics" }) %>
+
+## Keep reading
+
+[Google Analytics documentation](https://support.google.com/analytics)
diff --git a/articles/analytics/index.md b/articles/analytics/index.md
new file mode 100755
index 0000000000..b40e0508b0
--- /dev/null
+++ b/articles/analytics/index.md
@@ -0,0 +1,38 @@
+---
+url: /analytics
+section: articles
+classes: topic-page
+title: Analytics Integrations
+topics:
+ - analytics
+public: false
+contentType: index
+useCase:
+ - manage-analytics
+ - analyze-external-analytics
+---
+
+
+
+
Analytics Integrations
+
+ Setup and configure analytics integrations with Auth0.
+
+
+
+Analytics tools help you track users on your site or application. Integrating third-party analytics tools with Auth0 enables you to capture and measure identity specific events. You can use this data to create funnels, measure user retention, and improve your sign up flow.
+
+
+ Learn how to integrate Google Analytics into your application.
+
+
+
diff --git a/articles/analytics/integrations/_install.md b/articles/analytics/integrations/_install.md
deleted file mode 100644
index a89abef1c4..0000000000
--- a/articles/analytics/integrations/_install.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## Install
-
-To add the <%- name %> integration to your app, include a reference to the `Auth0 Analytics.js` script on any pages with Auth0 Lock. Include the script reference after Lock and set the configuration options before the script reference.
-
-```
-
-
-
-```
-
-::: note
-The script version above uses a placeholder version `X.Y.Z`. For example, to reference release 1.2.0 use `https://cdn.auth0.com/js/analytics/1.2.0/analytics.min.js`. To find the latest release, see the [releases on github](https://github.com/auth0/auth0-analytics.js/releases/).
-:::
\ No newline at end of file
diff --git a/articles/analytics/integrations/_usage.md b/articles/analytics/integrations/_usage.md
deleted file mode 100644
index 756e06685b..0000000000
--- a/articles/analytics/integrations/_usage.md
+++ /dev/null
@@ -1,19 +0,0 @@
-## Usage
-After installation on your site there is nothing else you need to do to start collecting data. Auth0 Analytics will immedately begin sending events to <%- name %>.
-
-You will see the following events being logged:
-
-* Auth0 Lock show
-* Auth0 Lock hide
-* Auth0 Lock unrecoverable_error
-* Auth0 Lock authenticated
-* Auth0 Lock authorization_error
-* Auth0 Lock forgot_password ready
-* Auth0 Lock forgot_password submit
-* Auth0 Lock signin submit
-* Auth0 Lock signup submit
-* Auth0 Lock federated login
-
-Note that some events that Lock emits like `hash_parsed` are not used for analytics purposes. Also, be aware that some events are only availible in newer versions of Lock. If you are using an older version of Lock you will only see some of these events. We suggest upgrading to the latest version of Lock to get the most of the Auth0 Analytics integration.
-
-For more information on the events that are sent see the [Lock API documentation](/libraries/lock/v10/api).
diff --git a/articles/analytics/integrations/facebook-analytics/index.md b/articles/analytics/integrations/facebook-analytics/index.md
deleted file mode 100644
index 73c4463346..0000000000
--- a/articles/analytics/integrations/facebook-analytics/index.md
+++ /dev/null
@@ -1,60 +0,0 @@
----
-description: This article explains how to install and configure the Facebook Analytics for Auth0 integration.
----
-# Facebook Analytics for Auth0
-
-This article explains how to install and configure the **Facebook Analytics for Auth0** integration. You can use this integration on your own page that is using [Lock](/libraries/lock) or you can use this on the [hosted Lock pages](/hosted-pages/login). Additionally, you will find instructions on how to configure funnels and reports inside of Facebook Analytics to get the most out of this integration.
-
-<%= include('../_install', { name: "Facebook Analytics" }) %>
-
-## Setup
-
-There are several ways you can use the Facebook Analytics integration. If you already have either the Facebook Tracking Pixel or the Facebook Javascript SDK referenced on your site, configure Auth0 Analytics with the `preload` option as shown below. If you don't have either script loaded you need to set your Facebook Analytics App ID using the Facebook Javascript SDK configuration below.
-
-### Using Facebook Javascript SDK (Recommended)
-
-The simplest configuration is to let the Analytics script load the Facebook Javascript SDK. You can do this by providing your Facebook Analytics App ID to the analytics options as shown below.
-
-```
-
-```
-
-If you have already loaded the Facebook Javascript SDK on your site, configure Auth0 Analytics to not load it again as shown below.
-
-```
-
-```
-
-### Using Facebook Pixel
-
-If you already have the Facebook Pixel installed on your site you can use that configuration mode. Note that with the Facebook Pixel, certain features of Facebook Analytics are not availible. The configuration for using the pixel is shown below.
-
-```
-
-```
-
-<%= include('../_usage', { name: "Facebook Analytics" }) %>
-
-## Reporting
-
-For the most up to date information on using Facebook Analytics, check out the [Facebook Analytics documentation](https://www.facebook.com/help/analytics/1710582659188030).
-
-We recommend [creating funnels](https://www.facebook.com/help/analytics/935921203105136) to measure the success of your aquistion and registration flows using these new events.
diff --git a/articles/analytics/integrations/google-analytics/index.md b/articles/analytics/integrations/google-analytics/index.md
deleted file mode 100644
index ab2a5a414e..0000000000
--- a/articles/analytics/integrations/google-analytics/index.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-description: This article explains how to install and configure the Google Analytics for Auth0 integration.
----
-# Google Analytics for Auth0
-
-This article explains how to install and configure the **Google Analytics for Auth0** integration. You can use this integration on your own page that is using Lock or you can use this on the hosted Lock pages. Additionally, you will find instructions on how to configure funnels and reports inside of Google Analytics to get the most out of this integration.
-
-<%= include('../_install', { name: "Google Analytics" }) %>
-
-## Setup
-
-There are several ways you can use the Google Analytics integration. If you already have the Google Analytics Script on your site, configure Auth0 Analytics with the `preload` option as shown below. If you don't have Google Analytics loaded you need to set your Google Analytics ID using the Google Analytics configuration below.
-
-### Google Analytics Script Already Loaded (Recommended)
-
-If you have already loaded the Google Analytics script loaded on your site, configure Auth0 Analytics to not load it again as shown below.
-
-```
-
-```
-
-### No Google Analytics Script
-
-If you are not using Google Analytics already you can have the Auth0 Analytics script load Google Analytics for you. To do this you need to set your Google Analytics ID in the options as shown below.
-
-```
-
-```
-
-<%= include('../_usage', { name: "Google Analytics" }) %>
-
-## Reporting
-
-For the most up to date information on using Google Analytics, check out the [Google Analytics documentation](https://support.google.com/analytics).
diff --git a/articles/analytics/integrations/index.md b/articles/analytics/integrations/index.md
deleted file mode 100644
index 34325341e5..0000000000
--- a/articles/analytics/integrations/index.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-url: /analytics/integrations
-section: articles
-classes: topic-page
-title: Analytics Integrations
----
-
-
-
-
Analytics Integrations
-
- How to setup and configure analytics integrations with Auth0.
-
-
-
-Analytics tools help you track users on your site or application. The Auth0 Analytics integrations enable you to capture and measure identity specific events. You can use this data to create funnels, measure user retention, and improve your sign up flow.
-
-
- This document will show you how to integrate Facebook Analytics into your application using either the Facebook JavaScript SDK or the Facebook Pixel.
-
- This document will show you how to integrate Google Analytics into your application.
-
-
-
diff --git a/articles/anomaly-detection/breached-passwords.md b/articles/anomaly-detection/breached-passwords.md
deleted file mode 100644
index 21e8182710..0000000000
--- a/articles/anomaly-detection/breached-passwords.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-description: Explains why a user received a breached password email and general web security tips.
----
-
-# Breached Password Security
-
-## What happened that I received an email saying "Please change your password immediately"?
-
-Your account could have possibly been hacked, compromised or stolen by a third party application that experienced a security breach. This breach did not happen to this account, but based on available data, your credentials may have been released. Since many people reuse passwords, we wanted to make sure you stay protected.
-
-You may also want to change your password at any other sites that you suspect you used a shared password.
-Here are links for password resets on commonly used sites:
-* [Google](https://www.google.com/accounts/recovery/)
-* [Facebook](https://www.facebook.com/settings)
-* [Twitter](https://twitter.com/settings/password)
-
-## General Security Tips
-
-You can't prevent certain sites from security breaches, but there are some things you can do to help keep your accounts safe.
-
-* **Check your emails carefully**
-Make sure to check where an email is coming from, and the links that they provide. Often phishing emails do not include your name but something generic such as "Dear Customer". Always do a password reset through the actual site itself.
-* **Never enter personal or financial information in an email**
-Emails in general are not very secure, so this is not a good way to communicate sensitive information. A trusted company/application would not ask for your information in this way. Also watch out to make sure you are not entering confidential information through false the links provided in emails. A secure website always starts with “https”.
-* **Never download files from unreliable sources**
-Most web browsers detect suspicious sites, when you try to access a malicious site, an alert message will appear. Never download files from suspicious emails or websites.
-* **Do not reuse passwords**
-When one site has a breach of user data, if you use the same credentials elsewhere, your information in other sites can also be accessed. There are many password tools out there to help you keep track of passwords.
-* **Use strong passwords**
-The longer a password is, the harder it becomes to guess. Try to make passwords long and use a mix of special characters, numbers and upper and lowercase letters.
-* **Keep software current**
-Applications release patches and updates when they find security vulnerabilities in their systems. Keeping your applications, web browsers and operating system up to date can help prevent security breaches.
\ No newline at end of file
diff --git a/articles/anomaly-detection/concepts/breached-passwords.md b/articles/anomaly-detection/concepts/breached-passwords.md
new file mode 100644
index 0000000000..92f077dc01
--- /dev/null
+++ b/articles/anomaly-detection/concepts/breached-passwords.md
@@ -0,0 +1,64 @@
+---
+title: Breached Password Security
+description: Understand why a user receives a breached password email and general web security tips.
+topics:
+ - security
+ - passwords
+contentType: concept
+useCase: customize-anomaly-detection
+v2: true
+---
+
+# Breached Password Security
+
+When a user receives an email requesting that they change their password immediately, it is because their account could be the victim of a security breach. This may be the result of a compromise by a third-party application that experienced a security breach. The breach may not have happened to this account, but based on available data, the user's credentials may have been released. Since many people reuse passwords, the request to change passwords is a precaution to make sure the user stays protected.
+
+Users may also want to change their password at any other sites where they suspect they used a shared password.
+
+## General security tips
+
+Users can't usually prevent certain sites from experiencing security breaches, but there are some things they can do to help keep their accounts safe.
+
+### Check emails carefully
+
+Check where an email is coming from and the links that they provide. Often phishing emails do not include a user's name but something generic such as "Dear Customer."
+
+### Reset passwords directly from sites
+
+Always do a password reset through the actual site itself not via potentially false links in emails. Also note that secure website URL always starts with `https`.
+
+Here are some links for password resets on commonly used sites:
+* [Google](https://www.google.com/accounts/recovery/)
+* [Facebook](https://www.facebook.com/settings)
+* [Twitter](https://twitter.com/settings/password)
+
+### Never enter personal or financial information in email
+
+Emails in general are not very secure and are not a good way to communicate sensitive information. A trusted company/application would not ask for information in this way. Make sure not to enter confidential information through false links in emails.
+
+### Never download files from unreliable sources
+
+Most web browsers detect suspicious sites. An alert should appear when you try to access a malicious site. Never download files from suspicious emails or websites.
+
+### Do not reuse passwords
+
+When one site has a breach of user data, if a user uses the same credentials elsewhere, information in other sites can also be accessed. The only way to prevent this is by not reusing passwords for multiple sites. The problem is that remembering countless passwords is frustrating and often impossible. One solution to this problem is the use of a password manager. There are many password managers available which can help users to use separate and secure passwords for each account, but at the same time not be responsible for remembering all of them.
+
+### Use strong passwords
+
+The longer a password is, the harder it becomes to be guessed via brute force methods. Many sites allow the use of pass-phrases (a phrase or sentence instead of just a complicate word.) Try to make passwords long and use a mix of special characters, numbers, and upper- and lowercase letters.
+
+### Keep software current
+
+Applications release patches and updates when they find security vulnerabilities in their systems. Keeping applications, web browsers, and operating systems up to date can help prevent security breaches.
+
+### Check the security of your email inbox
+
+If you use Gmail, Google offers the [Security Checkup](https://myaccount.google.com/security-checkup) tool to let you know if there are any security issues related to your inbox.
+
+You can also use third-party tools, such as websites like [HaveIBeenPwned](https://haveibeenpwned.com/PwnedWebsites) to see if there might be security issues associated with your email address.
+
+## Keep reading
+
+* [Anomaly Detection](/anomaly-detection)
+* [Customize Blocked Account Emails](/anomaly-detection/guides/customize-blocked-account-emails)
diff --git a/articles/anomaly-detection/guides/customize-blocked-account-emails.md b/articles/anomaly-detection/guides/customize-blocked-account-emails.md
new file mode 100644
index 0000000000..1347250973
--- /dev/null
+++ b/articles/anomaly-detection/guides/customize-blocked-account-emails.md
@@ -0,0 +1,30 @@
+---
+title: Customize Blocked Account Emails
+description: Learn how to customize blocked account emails.
+topics:
+ - security
+ - anomaly-detection
+ - brute-force-protection
+ - breached-password-detection
+contentType: how-to
+useCase: customize-anomaly-detection
+v2: true
+---
+# Customize Blocked Account Emails
+
+When Auth0 sends an email to a user to notify them of the [breached password block action](/anomaly-detection/references/breached-password-detection-triggers-actions), the message contains a link to re-enable the origin of the request.
+
+::: note
+Auth0 never blocks the user itself, just the attempts from the suspicious origin.
+:::
+
+The email sent to the user looks like this:
+
+
+
+You can customize the template used for this message on the [Dashboard](${manage_url}/#/emails) under __Emails > Templates > Blocked Account Email__.
+
+## Keep reading
+
+* Learn more about [email templates](/email/templates).
+* Understand [why a user receives a breached password email](/anomaly-detection/concepts/breached-passwords) and general web security tips.
diff --git a/articles/anomaly-detection/guides/enable-disable-brute-force-protection.md b/articles/anomaly-detection/guides/enable-disable-brute-force-protection.md
new file mode 100644
index 0000000000..e40844c3be
--- /dev/null
+++ b/articles/anomaly-detection/guides/enable-disable-brute-force-protection.md
@@ -0,0 +1,29 @@
+---
+title: Enable and Disable Brute-Force Protection
+description: Learn how to disable and enable brute-force protection.
+topics:
+ - security
+ - anomaly-detection
+ - brute-force-protection
+contentType: how-to
+useCase: customize-anomaly-detection
+v2: true
+---
+# Enable and Disable Brute-Force Protection
+
+Brute-force protection is enabled by default for all connections.
+
+
+
+::: warning
+Auth0 strongly recommends that you **do not** set the `brute_force_protection` flag to `false` (effectively disabling brute-force protection for the connection), however if you do, you can change it back in the [Dashboard](${manage_url}/#/anomaly).
+:::
+
+Once enabled, you can [customize](/anomaly-detection/guides/set-anomaly-detection-preferences#brute-force-protection-preferences) your brute-force protection settings.
+
+
+
+## Keep reading
+
+* [Brute-Force Protection Triggers and Actions](/anomaly-detection/references/brute-force-protection-triggers-actions)
+* [Set Anomaly Detection Preferences](/anomaly-detection/guides/set-anomaly-detection-preferences)
\ No newline at end of file
diff --git a/articles/anomaly-detection/guides/prevent-credential-stuffing-attacks.md b/articles/anomaly-detection/guides/prevent-credential-stuffing-attacks.md
new file mode 100644
index 0000000000..c4d5d0b291
--- /dev/null
+++ b/articles/anomaly-detection/guides/prevent-credential-stuffing-attacks.md
@@ -0,0 +1,91 @@
+---
+title: Prevent Credential Stuffing Attacks
+description: Learn how to prevent credential stuffing attacks on your system.
+beta: true
+topics:
+ - anomaly-detection
+ - credential-stuffing
+contentType: how-to
+useCase:
+ - prevent-credential-stuffing
+---
+# Prevent Credential Stuffing Attacks
+
+Credential stuffing attacks (also known as *list validation attacks*) occur when bad actors automate the process of trying username and password combinations (usually stolen from another site) for many accounts in a short period of time. According to recent statistics, as many as 71% of accounts use the same password across multiple sites so a credential stuffing attack has the potential to successfully log into your system.
+
+Consider, for example, the number of errors caused by an incorrect email or username (identified in the logs as type `fu`) for a particular tenant, which suggests an attack occurred November 20, with some abuse patterns afterwards:
+
+
+
+Auth0 provides a number of tools to combat credential stuffing attacks:
+
+* [Brute Force Protection](/anomaly-detection/guides/enable-disable-brute-force-protection) blocks login attempts after a number of consecutive failed logins.
+
+* [Breached Password Protection](/anomaly-detection/concepts/breached-passwords) identifies credentials that are known to be stolen.
+
+* [Multi-factor Authentication](/mfa) can be effective in preventing unauthorized logins, but it adds friction to the user experience.
+
+If you do not want to turn on additional features such as MFA, you can add **Automated Credential Stuffing Attack Protection** to provide a standard level of protection against credential stuffing attacks that does not add any friction to legitimate users.
+
+## How it works
+
+Auth0 uses a large amount of data to identify patterns that signal that a credential stuffing attack is taking place. Auth0 uses sophisticated algorithms to determine when bursts of traffic are likely to be from a bot or script. Users attempting to sign in from IPs which are determined to have a high likelihood of being a credential stuffing attack will see a Captcha step. The algorithms are designed so that this only happens for bad traffic; the objective is to not show any friction to legitimate users.
+
+
+
+## Enable automated credential stuffing attack protection
+
+### Prerequisites
+
+* Please read Auth0’s [Beta Service Terms](https://cdn.auth0.com/website/legal/terms/beta-service-terms-11-18-19.pdf) and acknowledge you have read and agreed to the terms by emailing **Antonio Fuentes** at **antonio.fuentes@auth0.com**.
+
+* Determine which type of login experience you have configured:
+
+ - Go to [Dashboard](${manage_url}/#).
+ - Navigate to **Universal Login**.
+ - Determine which login experience is selected (Classic or New).
+
+### If you are using New Universal Login
+
+No further configuration is required. If you are part of the Beta program, the Early Access features will work for your tenant immediately.
+
+### If you are using Classic Universal Login
+
+Determine if your page is customized.
+
+1. Select the **Login** tab.
+
+2. Verify the status of the toggle **Customize Login Page**.
+
+3. If it is on, you have a customized login page.
+
+### If you are using customized Classic Universal Login
+
+Upgrade your version of Lock.
+
+1. Navigate to the **Universal Login** section in the Dashboard.
+
+2. Select the **Login** tab.
+
+3. Update your version of Auth0’s Lock to version v11.20 by replacing the script tag with the tag for version v11.20.
+
+For example, replace this tag:
+```html
+
+```
+
+With the following:
+```html
+
+```
+
+## Performance impact
+
+This feature is intended to reduce the number of login attempts associated with automated or scripted credential stuffing attacks. It is not expected to cause a degradation in the latency or performance of the login flows. Auth0 monitors the impact on these metrics and will share them with you.
+
+In addition, you can look at the [tenant logs](/anomaly-detection/guides/use-tenant-data-for-anomaly-detection). Events that indicate a credential stuffing attack is happening.
+
+- `f`: failed login
+- `fu`: failed login due to invalid email/username
+
+If you have questions, you can contact Auth0 through your TAM or contact **antonio.fuentes@auth0.com**.
diff --git a/articles/anomaly-detection/guides/set-anomaly-detection-preferences.md b/articles/anomaly-detection/guides/set-anomaly-detection-preferences.md
new file mode 100644
index 0000000000..7096901ab2
--- /dev/null
+++ b/articles/anomaly-detection/guides/set-anomaly-detection-preferences.md
@@ -0,0 +1,70 @@
+---
+title: Set Anomaly Detection Preferences
+description: Learn how to set anomaly detection preferences in the Dashboard.
+topics:
+ - security
+ - anomaly-detection
+ - brute-force-protection
+ - breached-password-detection
+contentType: how-to
+useCase: customize-anomaly-detection
+v2: true
+---
+# Set Anomaly Detection Preferences
+
+Customize the actions that occur after the triggers in the **Anomaly Detection** section on the [Dashboard](${manage_url}/#/anomaly).
+
+::: warning
+Auth0 recommends that you **do not** make changes to your anomaly detection features with the Management API.
+:::
+
+
+
+## Brute-force protection preferences
+
+Brute-force protection is enabled by default for all connections. For more information, see [Enable and Disable Brute-Force Protection](/anomaly-detection/guides/enable-disable-brute-force-protection).
+
+::: warning
+Auth0 strongly recommends that you **do not** set the `brute_force_protection` flag to `false` (effectively disabling brute-force protection for the connection), however if you do, you can change it back in the [Dashboard](${manage_url}/#/anomaly).
+:::
+
+Limit the amount of signups and failed logins from a suspicious IP address. For more information, see [Brute-Force Protection Triggers and Actions](/anomaly-detection/references/brute-force-protection-triggers-actions).
+
+1. Click on the **Brute-force Protection** shield.
+
+
+
+2. Use the toggles to enable or disable actions for single or multiple user accounts.
+
+3. Add any IP addresses to the **Whitelist** field to avoid erroneously triggering the protection action.
+
+4. Click **Save** when you are finished.
+
+## Breached password detection preferences
+
+Set preferences for breached password detection actions. For more information, see [Breached Password Detection Triggers and Actions](/anomaly-detection/references/breached-password-detection-triggers-actions).
+
+1. Click on the **Breached-password Detection** shield.
+
+
+
+2. Use the toggles to enable or disable actions when login security breaches are detected.
+
+3. Determine how administrators are notified.
+
+4. Click **Save** when you are finished.
+
+## Restrictions and limitations
+
+Both brute-force protection and breached password detection depend on the IP address of the user. Because of this, the following use cases are *not* supported:
+
+* **Using the [Resource Owner](/api/authentication#resource-owner) from the backend of the application.** Using this call does not get the IP address of the user. See point 2 below as an alternative.
+
+* **Using [Resource Owner Password Grant](/api-auth/grant/password) from the backend of the application.** Using this call does not get the IP address of the user, however, you can [configure your application and send the IP address of the user as part of the request](/api-auth/tutorials/using-resource-owner-password-from-server-side) to make brute-force protection work correctly.
+
+* **Authenticating many users from the same IP address.** For example, users that are behind a proxy are more likely to reach these limits and trigger the associated protection. It is possible to configure a whitelist for the proxy's IP and CIDR range and avoid erroneously triggering the protection.
+
+## Keep reading
+
+* [Anomaly Detection](/anomaly-detection)
+* [Breached Password Security](/anomaly-detection/concepts/breached-passwords)
\ No newline at end of file
diff --git a/articles/anomaly-detection/guides/use-tenant-data-for-anomaly-detection.md b/articles/anomaly-detection/guides/use-tenant-data-for-anomaly-detection.md
new file mode 100644
index 0000000000..fd88341413
--- /dev/null
+++ b/articles/anomaly-detection/guides/use-tenant-data-for-anomaly-detection.md
@@ -0,0 +1,57 @@
+---
+description: Learn how to use tenant traffic log data to view anomaly detection events.
+topics:
+ - security
+ - anomaly-detection
+contentType: how-to
+useCase: tenant-logs
+---
+
+# View Anomaly Detection Events
+
+The tenant logs contain useful data that you can use to build charts to look at the profile of the traffic going through your tenant. This is helpful when evaluating anomaly detection activity.
+
+## Authentication failure events
+
+You can use the log data `event` field to view the tenant traffic data. We recommend building a daily histogram of failure events of the following types:
+
+| Event Code | Event |
+| -- | -- |
+| `f` | Failed login |
+| `fcoa` | Failed cross-origin authentication |
+| `feccft` | Failed exchange |
+| `fepft` | Failed exchange |
+| `fsa` | Failed silent authentication |
+| `fu` | Failed login (invalid email/username) |
+| `sepft` | Success exchange |
+
+These failure events depend on the flow you have set up with Auth0.
+
+The following example shows a credential stuffing attack on 11/20, with a large surge of events of type `fu` which is a failed username (typical of a credential stuffing attack).
+
+
+
+## Authenticaton failure events from distinct IPs
+
+You can use the `ip` event to see the number of distinct IPs that your failure traffic is coming from, in this case, the number of distinct IPs that correspond to your `fu` event traffic.
+
+## Anomaly detection events
+
+You can perform the same type of analysis with the events corresponding to anomaly detection events to see how many times they are triggered. Use the following log events which correspond to brute force detection with many accounts, one account, and breached password detection:
+
+| Event Code | Event |
+| -- | -- |
+| `limit_mu` | Blocked IP address |
+| `limit_wc` | Blocked account |
+| `pwd_leak` | Breached password |
+
+Here's an example of what that data might look like.
+
+
+
+## Keep reading
+
+* [Log Event Data](/logs/references/log-events-data)
+* [Log Search Query Syntax](/logs/references/query-syntax)
+* [Export Log Data to External Services](/extensions#Monitor)
+* [Retrieve Logs Using the Management API](/logs/guides/retrieve-logs-mgmt-api)
diff --git a/articles/anomaly-detection/index.md b/articles/anomaly-detection/index.md
index c2dbc44f3d..9dc98e5ece 100644
--- a/articles/anomaly-detection/index.md
+++ b/articles/anomaly-detection/index.md
@@ -1,113 +1,73 @@
---
-toc: true
-description: Explains all the types of Anomaly Detection provided by Auth0 and how to enable them.
-url: /anomaly-detection
+title: Anomaly Detection
+description: Understand how Auth0 detects anomalies to stop malicious attempts to access your application, alert you and your users of suspicious activity, and block further login attempts.
+toc: true
+topics:
+ - security
+ - anomaly-detection
+ - brute-force-protection
+ - breached-password-detection
+contentType: concept
+useCase: customize-anomaly-detection
+v2: true
---
-
# Anomaly Detection
-Auth0 provides built-in tools to detect anomalies and stop malicious attempts to access your application. Anomaly detection can alert you and your users of suspicious activity, as well as block further login attempts. You can set your preferences on the notifications that get sent and you can decide whether to block a suspicious IP address or not.
-
-## What Anomaly Detection Provides
-
-Currently Auth0 has three types of **shields** you can enable to handle anomalies and attacks. A **shield** specifies the **action** you wish to take given a specific **trigger**.
-
-A **trigger** is a suspicious event that is detected when someone is trying to login to your system, or there may have been a breached password with another 3rd party service.
+Auth0 can detect anomalies and stop malicious attempts to access your application. Anomaly detection can alert you and your users of suspicious activity, as well as block further login attempts. You can [set preferences](/anomaly-detection/guides/set-anomaly-detection-preferences) for notifications and decide whether to block a suspicious IP address or not.
-## Shields
+Auth0 has two types of **shields** to handle anomalies and attacks.
-### Brute-Force Protection
-There are two different triggers for the brute-force protection shield, for two slightly different attack scenarios.
+* [Brute-force protection](#brute-force-protection)
+* [Breached password detection](#breached-password-detection)
-**Trigger:** *10* failed login attempts into a single account from the same IP address.
+A **shield** specifies the **action** you wish to take given a specific **trigger**. A **trigger** is a suspicious event that is detected when someone is trying to login to your system, or there may have been a breached password with another third party service.
-**Actions**:
-* Send an email to the affected user (The email can be [customized](#customize-the-blocked-account-email))
-* Block the suspicious IP address
+Customize the actions in the **Anomaly Detection** section on the [Dashboard](${manage_url}/#/anomaly).
-::: panel Note
-The way this anomaly protection works is that if user with "user_id1" signs in from IP1 and fails to login consecutively for 10 attempts their login from this IP - IP1 will be blocked. Another user, say "user_id2" signing in from the same IP (IP1) will not be blocked. The mechanism to clear this block is described below.
-
-Currently the default trigger amount of 10 cannot be changed.
+::: note
+Auth0 recommends that you [create reports using tenant traffic data to see anomaly detection events](/anomaly-detection/guides/use-tenant-data-for-anomaly-detection).
:::
-If this block is triggered, it can be cleared the following ways:
-
-* An administrator removes the block via the [Dashboard](${manage_url}) (by clicking **unblock for all IPs** under the **ACTIONS** button when viewing the user's details) or by using the [Management API](/api/management/v2#!/User_Blocks/delete_user_blocks) ;
-* The User clicks on the "unblock" link provided in the email sent when the block went into effect;
-* The User changes their password.
-
-
-**Trigger:** *100* failed login attempts from a single IP address using different usernames, all with incorrect passwords in 24 hours. Or *50* sign ups attempts per minute from the same IP address.
-
-**Actions:**
-* Notify dashboard administrator(s)
-* Block suspicious addresses
-
-If this block is triggered, additional access attempts are released one at a time over the course of 24 hours until 100 attempts are allocated. More specifically, you will gain 100 attempts / 24 hours * 60 minutes = 1 additional attempt every 25 minutes.
-
-Auth0 does email the dashboard administrator(s) when this block is triggered. Within this email there's a link the owner can click on to remove the block.
-
-#### Restrictions Regarding Brute-Force Protection
-
-Both of these anomaly types depend on the IP address of the user. Because of this, the following use cases are *not* supported:
-
-1. Using the [Resource Owner](/api/authentication#resource-owner) from the backend of the application. Using this call does not get the IP address of the user. See point 2 below as an alternative.
-2. Using [Resource Owner Password Grant](/api-auth/grant/password) from the backend of the application. Using this call does not get the IP address of the user, however, you can [configure your application and send the IP address of the user as part of the request](/api-auth/tutorials/using-resource-owner-password-from-server-side) to make brute-force protection work correctly.
-3. Authenticating many users from the same IP address. For example, users that are behind a proxy are more likely to reach these limits and trigger the associated protection. It is possible to configure a whitelist for the proxy's IP and CIDR range and avoid erroneously triggering the protection.
-
-### Breached Password Detection
-
-Every day malicious hackers penetrate websites and applications, exposing thousands of email and passwords. Given that it's quite common for users to use the same password to login to multiples sites, this poses a problem, not only for the hacked system, but to any application that shares those credentials.
-
-Auth0 tracks large security breaches that are happening on major third party sites to help keep your users and system secure. By enabling Breached Password Detection, your users can be notified and/or blocked from logging in if we suspect their credentials were part of a published security breach.
-
-**Trigger:** Auth0 suspects that a specific user's credentials were included in a major public security breach.
-
-**Actions:**
-* Send an email to the affected user
-* Send an email to dashboard owners immediately, and/or have a daily/weekly/monthly summary
-* Block login attempts for suspected user accounts using that username and password combination
-
-This block remains in place until the user changes their password.
-
-:::note
-Watch our [Breached Password Detection 101 video tutorial](https://auth0.com/resources/videos/learn-about-breached-password-detection).
-:::
-
-## Setting Your Preferences
-
-To customize the **actions** that get taken from the **triggers**, go to the [Anomaly Detection](${manage_url}/#/anomaly) section on the dashboard.
-
-
+## Brute-force protection
-You can use the toggle to disable all the actions of a certain shield. Or to enable/disable certain actions, click on the shield that has the action in it that you wish to change.
+Brute-force protection is [enabled by default](/anomaly-detection/guides/enable-disable-brute-force-protection) for all connections. There are two different [triggers](/anomaly-detection/references/brute-force-protection-triggers-actions) for the brute-force protection shield, for two slightly different attack scenarios.
-Then you can use the toggle to enable/disable an action.
+* 10 consecutive failed login attempts for the same user and from the same IP address
+* 100 failed login attempts from the same IP address in 24 hours *or* 50 sign up attempts per minute from the same IP address
-### Brute-force Protection
+For example, if a user with *user_id1* signs in from *IP1* and fails to login consecutively for 10 attempts, their log in attempt from this *IP1* will be blocked. Another user, *user_id2*, signing in from *IP1* will not be blocked.
-
+## Breached password detection
-Here you can also add any IP addresses to the **Whitelist** field to avoid erroneously triggering the protection.
+Every day, malicious hackers penetrate websites and applications, exposing thousands of email and passwords. Because it's common for users to use the same password to login to multiples sites, this poses a problem, not only for the hacked system, but to any application that shares those [breached passwords](/anomaly-detection/concepts/breached-passwords).
-Click **Save** when you have finished.
+Auth0 tracks large security breaches that are happening on major third party sites to help keep your users and system secure. By [enabling breached password detection](/anomaly-detection/guides/set-anomaly-detection-preferences), when a [trigger](/anomaly-detection/references/breached-password-detection-triggers-actions) occurs, your users can be notified and/or blocked from logging in if we suspect their credentials were part of a published security breach. You can [customize blocked account emails](/anomaly-detection/guides/customize-blocked-account-emails).
-### Breached-password Detection
+## Frequently asked questions
-
+* **Is the user notified at every login?**
+We send one email every hour, regardless of the number of logins. For example, if a user tries to log in 200 times in 1 hour and 30 minutes, we will send 2 emails.
-Click **Save** when you have finished.
+* **Is there a limit to the number of times a user will be notified?**
+Users will only be notified once per hour.
-### Customize the Blocked Account Email
+* **How often does Auth0 email administrators when traffic is blocked using Brute Force Protection for multiple accounts?**
+In the event of an ongoing attack, traffic can be blocked from thousands of IP addresses at a time. Auth0 will send a single email to each administrator every hour that traffic is blocked, regardless of the number of IPs involved in the attack.
-When Auth0 sends an email to a user to notify them of the block, the message contains a link to re-enable the origin of the request. Notice that Auth0 never blocks the user itself, just the attempts from the suspicious origin.
+* **For how long is the reset password link, included in the breached password email, valid?**
+Password reset links are valid for 5 days.
-The email sent to the user looks like this:
+* **Is there a test dataset of breached passwords?**
+You can test with **leak-test@example.com** as the email and **Paaf213XXYYZZ** as the password.
-
+* **Does the breached password detection work when logging in using the Resource Owner password grant?**
+Yes.
-The template used for this message can be customized on the [Dashboard](${manage_url}/#/emails) under __Emails > Templates > Blocked Account Email__.
+* **Does the breached password detection feature work with a custom database?**
+Yes.
-[Learn more about Customizing your Emails](/email/templates)
+* **What Redirect URL applies to the *Change password* link included in the breached password notification email?**
+The **RedirectTo** URL is the URL listed in the Dashboard in [Emails > Templates > Change Password Template](${manage_url}/#/emails).
+* **Is there a way to configure the Redirect URL and the length of time that the change password link is valid?**
+You can configure the **URL Lifetime** and **Redirect To** values in the Dashboard by going to [Emails > Templates > Change Password Template](${manage_url}/#/emails).
\ No newline at end of file
diff --git a/articles/anomaly-detection/references/breached-password-detection-triggers-actions.md b/articles/anomaly-detection/references/breached-password-detection-triggers-actions.md
new file mode 100644
index 0000000000..c7e0e93b8b
--- /dev/null
+++ b/articles/anomaly-detection/references/breached-password-detection-triggers-actions.md
@@ -0,0 +1,35 @@
+---
+title: Breached Password Detection Triggers and Actions
+description: Breached password detection triggers and actions taken upon anomaly detection and how blocks are cleared.
+topics:
+ - security
+ - anomaly-detection
+ - breached-password-detection
+contentType: reference
+useCase: customize-anomaly-detection
+v2: true
+---
+# Breached Password Detection Triggers and Actions
+
+## Trigger
+
+A trigger occurs when Auth0 suspects that a specific user's credentials were included in a major public security breach.
+
+::: panel Video Tutorial
+Watch our [Breached Password Detection 101 video tutorial](https://auth0.com/resources/videos/learn-about-breached-password-detection).
+:::
+
+## Actions
+
+* Send an email to the affected user.
+* Send an email to dashboard owners immediately, and/or have a daily/weekly/monthly summary.
+* Block login attempts for suspected user accounts using that username and password combination.
+
+## Remove block
+
+This block remains in place until the user changes their password.
+
+## Keep reading
+
+* [Anomaly Detection](/anomaly-detection)
+* [Breached Password Security](/anomaly-detection/concepts/breached-passwords)
\ No newline at end of file
diff --git a/articles/anomaly-detection/references/brute-force-protection-triggers-actions.md b/articles/anomaly-detection/references/brute-force-protection-triggers-actions.md
new file mode 100644
index 0000000000..3342464d8f
--- /dev/null
+++ b/articles/anomaly-detection/references/brute-force-protection-triggers-actions.md
@@ -0,0 +1,64 @@
+---
+title: Brute-Force Protection Triggers and Actions
+description: Brute-force protection triggers and actions taken upon anomaly detection and how blocks are cleared.
+topics:
+ - security
+ - anomaly-detection
+ - brute-force-protection
+contentType: reference
+useCase: customize-anomaly-detection
+v2: true
+---
+# Brute-Force Protection Triggers and Actions
+
+## 10 failed login attempts
+
+### Trigger
+
+This trigger occurs when there are 10 failed login attempts into a single account from the same IP address.
+
+::: note
+The default trigger amount of 10 cannot be changed.
+:::
+
+### Actions
+
+* Send an email to the affected user. (You can [customize the email](/anomaly-detection/guides/customize-blocked-account-emails).)
+* Block the suspicious IP address for that user.
+
+### Remove block
+
+If this block is triggered, it can be cleared the following ways:
+
+* An administrator removes the block via the [Dashboard](${manage_url}) (by clicking **unblock for all IPs** under the **ACTIONS** button when viewing the user's details) or by using the [Management API](/api/management/v2#!/User_Blocks/delete_user_blocks).
+* The user clicks on the **unblock** link provided in the email sent when the block went into effect.
+* The user changes their password.
+
+## 100 failed login attempts *or* 50 sign up attempts
+
+### Triggers
+
+A trigger occurs when there are 100 failed login attempts from one IP address using different usernames with incorrect passwords in 24 hours.
+
+Another trigger occurs if there are 50 sign up attempts per minute from the same IP address.
+
+### Actions
+
+* Notify dashboard administrator(s).
+* Block suspicious addresses for 15 minutes.
+
+If this block is triggered, additional access attempts are released one-at-a-time over the course of 24 hours until 100 attempts are allocated. This results in approximately 1 additional attempt every 15 minutes.
+
+### Remove block
+
+Auth0 emails the dashboard administrator(s) when this block is triggered. The email contains a link that the owner can click to navigate to tenant logs to examine which IPs have been blocked. Recent blocks can be found using this query:
+```
+type:limit_mu
+```
+Blocks can then be removed using the [Management API](/api/management/v2#!/Anomaly/delete_ips_by_id).
+
+## Keep reading
+
+* [Anomaly Detection](/anomaly-detection)
+* [Set Anomaly Detection Preferences](/anomaly-detection/guides/set-anomaly-detection-preferences)
+* [Enable and Disable Brute-Force Protection](/anomaly-detection/guides/enable-disable-brute-force-protection)
diff --git a/articles/api-auth/_includes/_ropg-warning.md b/articles/api-auth/_includes/_ropg-warning.md
new file mode 100644
index 0000000000..c19c5320ac
--- /dev/null
+++ b/articles/api-auth/_includes/_ropg-warning.md
@@ -0,0 +1,9 @@
+::: warning
+Since the Resource Owner Password Grant (ROPG) flow involves the client handling the user's password, it **must not be used by third-party clients**. In this flow, the user's username and password are exchanged directly for an Access Token.
+
+Only consider using it when there is a high degree of trust between the user and the application and when other authorization flows (such as redirect-based flows) are not available.
+
+Instead, Auth0 recommends:
+* For confidential clients, like Regular Web Applications, use the [Authorization Code Flow](/flows/concepts/auth-code).
+* For public clients, like Native/Mobile Apps and Single-Page Applications, use the [Authorization Code Flow with PKCE](/flows/concepts/auth-code-pkce).
+:::
diff --git a/articles/api-auth/apis.md b/articles/api-auth/apis.md
index efde495062..da33b407f4 100644
--- a/articles/api-auth/apis.md
+++ b/articles/api-auth/apis.md
@@ -4,24 +4,24 @@ toc: true
title: APIs Overview
description: Learn the basics of APIs, their role in OAuth and how to configure an API in Auth0 Dashboard.
crews: crew-2
+topics:
+ - api-authentication
+ - oidc
+ - apis
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
# APIs
-<%= include('../_includes/_pipeline2') %>
-
-## Overview
-
An API is an entity that represents an external resource, capable of accepting and responding to protected resource requests made by applications. At the [OAuth2 spec](https://tools.ietf.org/html/rfc6749) an API maps to the **Resource Server**.
-When an application wants to access an API's protected resources it must provide an [Access Token](/tokens/access-token). The same Access Token can be used to access the API's resources without having to authenticate again, until it expires.
+When an application wants to access an API's protected resources it must provide an Access Token. The same Access Token can be used to access the API's resources without having to authenticate again, until it expires.
-Each API has a set of defined permissions. Applications can request a subset of those defined permissions when they execute the authorization flow, and include them in the Access Token as part of the **scope** request parameter.
+Each API has a set of defined permissions. Applications can request a subset of those defined permissions when they execute the authorization flow, and include them in the Access Token as part of the **scope** request parameter.
-For example, an API that holds a user's appointments, may accept two different levels of authorization: read only (scope `read:appointments`) or write (scope `write:appointments`). When an application asks the API to list a user's appointments, then the Access Token should contain the `read:appointments` scope. In order to edit an existing appointment or create a new one, the Access Token should contain the `write:appointments` scope.
-
-::: note
-For more information on tokens please refer to: [Tokens used by Auth0](/tokens).
-:::
+For example, an API that holds a user's appointments, may accept two different levels of authorization: read only (scope `read:appointments`) or write (scope `write:appointments`). When an application asks the API to list a user's appointments, then the Access Token should contain the `read:appointments` scope. In order to edit an existing appointment or create a new one, the Access Token should contain the `write:appointments` scope. See [Tokens](/tokens) for more information.
## How to configure an API in Auth0
@@ -39,9 +39,9 @@ You need to provide the following information for your API:
- **Name**: a friendly name for the API. Does not affect any functionality.
-- **Identifier**: a unique identifier for the API. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all. This value **cannot be modified** afterwards.
+- **Identifier**: a unique identifier for the API. Auth0 recommends using a URL. Auth0 does differentiate between URLs that include the last forward slash. For example, https://example.com and https://example.com/ are two different identifiers. The URL does not have to be a publicly available URL. Auth0 will not call your API. This value **cannot** be modified afterwards.
-- **Signing Algorithm**: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting `RS256` the token will be signed with the tenant's private key. For more details on the signing algorithms go to the [Signing Algorithms paragraph](#signing-algorithms).
+- **Signing Algorithm**: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting `RS256` the token will be signed with the tenant's private key. To learn more about signing algorithms, see [Signing Algorithms paragraph](/tokens/concepts/signing-algorithms).
Fill in the required information and click the **Create** button.
@@ -49,19 +49,16 @@ Once you do so you will be navigated to the *Quick Start* of your API. Here you

-::: note
-Keep in mind that we are working on building quickstarts for more stacks, apart from those currently available.
-:::
The other available views for your API are:
-- **Settings**: lists the settings for your API. Some are editable. Here you can change the token expiration time and enable offline access (this way Auth0 will allow your applications to ask for Refresh Tokens for this API). For details refer to the [API Settings paragraph](#api-settings).
+- **Settings**: lists the settings for your API. Some are editable. Here you can change the token expiration time and enable offline access (this way Auth0 will allow your applications to ask for Refresh Tokens for this API). For details refer to the [API Settings paragraph](#api-settings).
- **Scopes**: here you can define the scopes for this API, by setting a name and a description.
-- **Machine to Machine Applications**: lists your Machine to Machine Applications. You can authorize which Machine to Machine Applications can request Access Tokens for your API. You can optionally select a subset of the defined scopes to further limit the access that an authorized your application has. Only Machine to Machine Applications require explicit permission. That is because, when you authorize a Machine to Machine Applications to access an API, Auth0 is creating an Application Grant for that application. For more details on this case refer to: [Setting up a Client Credentials Grant using the Management Dashboard](/api-auth/config/using-the-auth0-dashboard).
+- **Machine to Machine Applications**: lists all applications for which the **Client Credentials** grant is **enabled**. By default, this grant is **enabled** for [Regular Web Applications and Machine to Machine Applications](/applications). You can authorize any of these applications to request Access Tokens for your API. Optionally, you can select a subset of the defined scopes to limit your authorized application's access.
-- **Test**: from this view you can execute a sample Client Credentials flow with any of your Authorized Machine to Machine Applications to check that everything is working as expected.
+- **Test**: from this view, you can execute a sample Client Credentials flow with any of your authorized applications to check that everything is working as expected.
### API Settings
@@ -73,52 +70,16 @@ Click on the *Settings* tab of your [API](${manage_url}/#/apis) to review the av
- **Identifier**: A unique identifier for your API. This value is set upon API creation and cannot be modified afterwards. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all.
-- **Token Expiration (Seconds)**: The amount of time (in seconds) before the Auth0 `access_token` expires.
+- **Token Expiration (Seconds)**: The amount of time (in seconds) before the Auth0 Access Token expires. The default value is 86400 seconds (24 hours). The maximum value you can set is 2592000 seconds (30 days).
-- **Allow Skipping User Consent**: When a first party application requests authorized access against an API with the *Allow Skipping User Consent* flag set, the User Consent dialog will not be shown to the final user. Note that if the hostname of your application's **callbackURL** is `localhost` or `127.0.0.1` the consent dialog will always be displayed.
+- **Allow Skipping User Consent**: When a first party application requests authorized access against an API with the *Allow Skipping User Consent* flag set, the User Consent dialog will not be shown to the final user. Note that if the hostname of your application's **callback URL** is `localhost` or `127.0.0.1` the consent dialog will always be displayed.
- **Allow Offline Access**: If this setting is enabled, Auth0 will allow applications to ask for Refresh Tokens for this API.
-- **Signing Algorithm**: The algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting `RS256` (recommended) the token will be signed with the tenant's private key. This value is set upon API creation and cannot be modified afterwards. For more details on the signing algorithms see the [Signing Algorithms paragraph](#signing-algorithms) below.
-
-### Signing Algorithms
-
-When you create an API you have to select the algorithm your tokens will be signed with. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
-
-::: note
-The signature is part of a JWT. If you are not familiar with the JWT structure please refer to: [JSON Web Tokens (JWTs) in Auth0](/jwt#what-is-the-json-web-token-structure-).
-:::
-
-To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. That algorithm, which is part of the JWT header, is the one you select for your API: `HS256` or `RS256`.
+- **Signing Algorithm**: The algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting `RS256` (recommended) the token will be signed with the tenant's private key. This value is set upon API creation and cannot be modified afterwards. To learn more about signing algorithms, see [Signing Algorithms](/tokens/concepts/signing-algorithms).
-- **RS256** is an [asymmetric algorithm](https://en.wikipedia.org/wiki/Public-key_cryptography) which means that there are two keys: one public and one private (secret). Auth0 has the secret key, which is used to generate the signature, and the consumer of the JWT has the public key, which is used to validate the signature.
+## Keep reading
-- **HS256** is a [symmetric algorithm](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which means that there is only one secret key, shared between the two parties. The same key is used both to generate the signature and to validate it. Special care should be taken in order for the key to remain confidential.
-
-The most secure practice, and our recommendation, is to use **RS256**. Some of the reasons are:
-
-- With RS256 you are sure that only the holder of the private key (Auth0) can sign tokens, while anyone can check if the token is valid using the public key.
-
-- Under HS256, if the secret key is compromised (e.g. by the application) you would have to re-deploy the API with the new secret.
-
-- With RS256 you can request a token that is valid for multiple audiences.
-
-- With RS256 you can implement key rotation without having to re-deploy the API with the new secret.
-
-::: panel Verify an RS256 signed token
-Go to [Dashboard > Applications](${manage_url}/#/applications). Open the **Settings** of your applications, scroll down and open **Advanced Settings**. Open the **Certificates** tab and you will find the Public Key in the **Signing Certificate** field.
-
-If you want to use the Public Key to verify a JWT signature on [JWT.io](https://jwt.io/), you can copy the Public Key and paste it in the **Public Key or Certificate** field under the **Verify Signature** section on the [JWT.io](https://jwt.io/) website.
-
-If you want to verify the signature of a token from one of your applications, we recommend that you get the Public Key from your tenant's [JSON Web Key Set (JWKS)](/jwks). Your tenant's JWKS is `https://${account.namespace}/.well-known/jwks.json`.
-:::
-
-For a more detailed overview of the JWT signing algorithms refer to: [JSON Web Token (JWT) Signing Algorithms Overview](https://auth0.com/blog/json-web-token-signing-algorithms-overview/).
-
-## Keep Reading
-
-::: next-steps
- [API Authorization landing page](/api-auth)
- [Identify the proper OAuth 2.0 flow for your use case](/api-auth/which-oauth-flow-to-use)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
-:::
+- [Tokens](/tokens)
diff --git a/articles/api-auth/blacklists-vs-grants.md b/articles/api-auth/blacklists-vs-grants.md
index 11b22821aa..8a8fbedf29 100644
--- a/articles/api-auth/blacklists-vs-grants.md
+++ b/articles/api-auth/blacklists-vs-grants.md
@@ -1,10 +1,20 @@
---
-description: This document covers blacklists vs. grants when it comes handling tokens.
+description: Understand blacklists vs. grants when it comes handling tokens.
+topics:
+ - api-authentication
+ - oidc
+ - security
+ - blacklists
+ - application-grants
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
# Blacklists and Application Grants
-Let's say that you're using a non-interactive [application](/application) to access your API. You have a partner that calls your API, and at the end of your existing contract, you and your partner decide not to renew your partnership. As such, you now want to remove your partner's access to your API. The issue, however, is that you've given your partner an [Access Token](/tokens/access-token) that lasts for a month.
+Let's say that you're using a machine to machine [application](/application) to access your API. You have a partner that calls your API, and at the end of your existing contract, you and your partner decide not to renew your partnership. As such, you now want to remove your partner's access to your API. The issue, however, is that you've given your partner an Access Token that lasts for a month.
* What can you do in this situation?
* How might you configure your Auth0 environment to make such situations easier to handle in the future?
@@ -20,14 +30,10 @@ We will then compare the two methods and provide our recommendations.
Let's say that you grant access to your API to anyone in possession of the appropriate Access Token. One method of revoking access to a user is to blacklist their token so that it can no longer be used.
-::: note
-Please see the Auth0 blog for an in-depth treatment on [Blacklisting JSON Web Token API Keys](https://auth0.com/blog/blacklist-json-web-token-api-keys/).
-:::
-
-Auth0-issued tokens are [JWTs](/jwt), so you can set the JWT ID, or `jti`, for the token by including it in the token payload's `jwtid` field. With the `jti` in hand, you can make the appropriate `POST` call to the Management API's [blacklist a token endpoint](/api/management/v2#!/Blacklists/post_tokens). You'll need to provide the JWT's `aud` and `jti` claims.
+Auth0-issued tokens are [JWTs](/tokens/concepts/jwts), so you can set the JWT ID, or `jti`, for the token by including it in the token payload's `jwtid` field. With the `jti` in hand, you can make the appropriate `POST` call to the Management API's [blacklist a token endpoint](/api/management/v2#!/Blacklists/post_tokens). You'll need to provide the JWT's `aud` and `jti` claims.
::: panel Add a JWT ID
-You can add `jti` via a [rule](/rule). Here's a simple example using UUID:
+You can add `jti` via a [rule](/rules). Here's a simple example using UUID:
```js
function (user, context, callback) {
diff --git a/articles/api-auth/config/using-the-auth0-dashboard.md b/articles/api-auth/config/using-the-auth0-dashboard.md
index e459277d3a..dde2b216f6 100644
--- a/articles/api-auth/config/using-the-auth0-dashboard.md
+++ b/articles/api-auth/config/using-the-auth0-dashboard.md
@@ -1,46 +1,33 @@
---
-description: How to set up a Client Credentials Grant using the Auth0 Dashboard
+description: How to set up a Client Grant using the Auth0 Dashboard
crews: crew-2
+topics:
+ - client-credentials
+ - api-authorization
+contentType: how-to
+useCase: secure-api
---
-# Set up a Client Credentials Grant using the Dashboard
+# Set Up Client Credentials Grants Using the Dashboard
-<%= include('../../_includes/_pipeline2') %>
+Auth0 lets you authorize applications that have the **Client Credentials** grant type enabled to call APIs using the [Client Credentials Flow](/flows/concepts/client-credentials).
-1. Open the Auth0 Management Dashboard and browse to the [Applications section](${manage_url}/#/applications).
+By default, the **Client Credentials** grant is enabled for all Machine-to-Machine Applications and Regular Web Applications, but they are _not yet_ authorized to call any API.
-2. Click on **Create Application** to begin creating a new application (if you have multiple applications needing access to the API, you'll need to create an Auth0 app for *each*). You'll be asked what type of application you'd like to create, so select **Machine to Machine Application**. Click **Create** to proceed.
+To authorize the applications to call an API:
-
+1. Open the Auth0 Management Dashboard and browse to the [API section](${manage_url}/#/apis).
-3. Navigate to the [API section](${manage_url}/#/apis) and create a new API.
+2. Select the API you want to invoke using the **Client Credentials** Grant.
-Enter a friendly name and an identifier. Ideally, this identifier should be the public endpoint of the API, but any valid URN is acceptable. This API will be represented by your **Resource Server**.
+3. Under the **Authorized Application** tab, look for the application you want to authorize, click the Authorize button, and optionally, select the list of scopes that will be granted in the Access Token. This will create a 'client grant' in Auth0, which will allow the application to call the API.
-The selection of the **Signing Algorithm** will dictate how the API will validate the Access Tokens it receives:
-* HS256 (symmetric): signed using the resource server's signing secret
-* RS256 (asymmetric): signed using Auth0's private key for your account. Verification is done using the corresponding public key, which can be found at the following standard [JWKS (JSON Web Key set)](/jwks) URL: [https://${account.namespace}/.well-known/jwks.json](https://${account.namespace}/.well-known/jwks.json)
+
-
-
-::: note
-There will already be an `Auth0 Management API` that represents Auth0's APIv2. You can authorize applications to request tokens from this API as well.
-:::
-
-4. (Optional) Define some scopes by browsing to the **Scopes** tab. A scope is a claim that may be issued as part of the Access Token. With this information, the API can enforce fine-grained authorization.
-
- 
-
-5. Authorize a consumer application. Under the **Machine to Machine Application** tab, you can authorize your applications that will be the consumers of the API. This will create a `client grant` for each application and will allow you to generate Access Tokens for these applications to call your API. Optionally, you can select a subset of scopes to be granted to this application as part of the Access Token. Scopes allow the API to enforce fine-grained authorization.
-
- 
-
-6. Setup your API to accept Access Tokens. The **Quickstart** tab provides you with code snippets for different languages and will guide you through bootstrapping your API, depending on the selected **Signing Algorithm**.
+4. In the Test tab, you can select the application to which you granted access, and see the Access Tokens that will be generated for it.
## Keep reading
-:::next-steps
-* [How to implement the Client Credentials Grant](/api-auth/tutorials/client-credentials)
-* [How to change the scopes and add custom claims to a token using Hooks](/api-auth/tutorials/client-credentials/customize-with-hooks)
-* [How to add custom claims to a token using Rules](/scopes#custom-claims)
-:::
+* [Call API using the Client Credentials Flow](/flows/guides/client-credentials/call-api-client-credentials)
+* [Use Hooks with Client Credentials Grant](/api-auth/tutorials/client-credentials/customize-with-hooks)
+* [Add Custom Claims Tokens Using Rules](/scopes/current/sample-use-cases#add-custom-claims-to-a-token)
diff --git a/articles/api-auth/config/using-the-management-api.md b/articles/api-auth/config/using-the-management-api.md
index f27b638dda..fc9e75f35a 100644
--- a/articles/api-auth/config/using-the-management-api.md
+++ b/articles/api-auth/config/using-the-management-api.md
@@ -1,86 +1,34 @@
---
-title: Set up a Client Credentials Grant using the Management API
-description: How to set up a Client Credentials Grant using the Management API.
+description: Learn how to set up a Client Credentials Grant using the Management API.
crews: crew-2
+topics:
+ - client-credentials
+ - api-authorization
+contentType: how-to
+useCase: secure-api
---
-# Set up a Client Credentials Grant using the Management API
+# Set Up Client Credentials Grants Using the Management API
-<%= include('../../_includes/_pipeline2') %>
+Auth0 lets you authorize applications that have the Client Credentials grant type enabled to call APIs using the [Client Credentials Flow](/flows/concepts/client-credentials).
-If you do not want to use the Auth0 Dashboard to create a Resource Server or you need to create one programmatically, you can use our Management API v2.
+By default, all Machine-to-Machine Applications and Regular Web Applications have the 'Client Credentials' grant enabled, but they are not authorized to call any API.
-You will need the following:
-
-- A Management APIv2 token with the appropriate scopes. For details on how to get one refer to [The Auth0 Management APIv2 Token](/api/management/v2/tokens).
-- The Application information (`Client_Id` and `Client_Secret`) for the Machine to Machine Application that should already be created and visible in your [Auth0 dashboard](${manage_url}/#/applications).
-
-## 1. Create your Resource Server
-
-Let's start by creating the Resource Server. This is the entity that represents the API that you want to issue Access Tokens for, identified by a friendly name and a URN identifier.
-
-The following restrictions apply to the identifier:
-- It must be a valid URN.
-- It cannot be modified after creation.
-- It must be unique throughout your tenant.
-
-We recommend using your public API endpoint as an identifier.
-
-To create a Resource Server send a `POST` request to the [/resource-servers endpoint of the Management APIv2](/api/management/v2#!/Resource_Servers/post_resource_servers) with an `access_token` that has the resource server scope (`scope:resource_server`).
-
-The following example uses _"My Sample API"_ as the name and _"https://my-api-uri"_ as the identifier.
+If you want to call an API from these applications, you first need to authorize the application to call the API and specify the scopes that will be granted. You can do that [using the Dashboard](/api-auth/config/using-the-auth0-dashboard), or follow the steps below to use the API.
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/api/v2/resource-servers",
- "headers": [
- { "name": "Content-Type", "value": "application/json" },
- { "name": "authorization", "value": "Bearer Auth0_MGMT_API_ACCESS_TOKEN" }
- ],
- "postData": {
- "mimeType": "application/json",
- "text": "{\"name\":\"My Sample API\",\"identifier\": \"https://my-api-urn\",\"signing_alg\": \"RS256\",\"scopes\": [{ \"value\": \"sample-scope\", \"description\": \"Description for Sample Scope\"}]}"
- }
-}
-```
-
-::: note
- You can include multiple scopes. This array represents the universe of scopes your API will support. You can modify this later by issuing a PATCH operation.
-:::
-
-Sample response:
+You will need the following:
-```json
-{
- "id": "56f0131ffdf1c311694f4cc7",
- "name": "My Sample API",
- "identifier": "https://my-api-urn",
- "scopes": [
- {
- "value": "sample-scope",
- "description": "Description for Sample Scope"
- }
- ],
- "signing_alg": "RS256",
- "signing_secret": "FF1prn9UxZotnolsDVwEJhqqyRmwdSu5",
- "token_lifetime": 86400
-}
-```
+- A Management API Access Token with the `create:client_grants` scopes. For details on how to get one, refer to [Access Tokens for the Management API](/api/management/v2/tokens).
-Note the following:
-- The `identifier` value (`https://my-api-urn`) will be used from now on as the `audience` for any OAuth 2.0 grant, that wants to access this API.
-- The algorithm that your API will use to sign tokens will be the __RS256__ (`signing_alg`).
-- The secret used to sign the tokens will be `FF1prn9UxZotnolsDVwEJhqqyRmwdSu5` (`signing_secret`).
-- The generated tokens will expire after `86400` seconds (`token_lifetime`).
+- The application information (`Client_Id` and `Client_Secret`) for the application you want to authorize [Auth0 dashboard](${manage_url}/#/applications).
-## 2. Authorize the Application
+- The API identifier for the API you want to invoke (${manage_url}/#/apis).
-Now that the API and the Application are defined in Auth0, you can create a trust relationship between them. To do so, authorize the Application to access the API, while defining the scopes that should be given to the Application (meaning the actions the Application will be able to perform on the API).
+## Authorize the Application
-To authorize your Application send a `POST` request to the [/client-grants endpoint of the Management APIv2](/api/management/v2#!/Client_Grants/post_client_grants) with an `access_token` that has the create application grants scope (`create:client_grantss`).
+To authorize your Application, send a `POST` request to the [/client-grants endpoint of the Management APIv2](/api/management/v2#!/Client_Grants/post_client_grants) with the Management API Access Token.
-The following example authorizes the Application with Id `${account.clientId}`, to access the API with Identifier `https://my-api-urn`, while granting the scope `sample-scope`.
+The following example authorizes the application with Id `${account.clientId}`, to access the API with Identifier `https://my-api-urn`, while granting the scope `sample-scope`.
```har
{
@@ -110,12 +58,12 @@ Sample response:
}
```
-That's it, you are done! Now that all the elements are in place, you can request Access Tokens for your API from Auth0.
+That's it, you are done! Now that all the elements are in place, you can request Access Tokens for your API from Auth0 using the Client Credentials Flow.
## Keep reading
:::next-steps
-* [How to implement the Client Credentials Grant](/api-auth/tutorials/client-credentials)
+* [Call API using the Client Credentials Flow](/flows/guides/client-credentials/call-api-client-credentials)
* [How to change the scopes and add custom claims to a token using Hooks](/api-auth/tutorials/client-credentials/customize-with-hooks)
-* [How to add custom claims to a token using Rules](/scopes#custom-claims)
+* [How to add custom claims to a token using Rules](/scopes/current/sample-use-cases#add-custom-claims-to-a-token)
:::
diff --git a/articles/api-auth/dynamic-client-registration.md b/articles/api-auth/dynamic-client-registration.md
index 06f3be5a3f..6bac759f08 100644
--- a/articles/api-auth/dynamic-client-registration.md
+++ b/articles/api-auth/dynamic-client-registration.md
@@ -1,35 +1,30 @@
---
-title: Dynamic Client Registration
-description: How to dynamically register clients with Auth0 using the Management API
+description: Learn how to dynamically register applications with Auth0 using the Management API.
crews: crew-2
toc: true
+topics:
+ - applications
+contentType: how-to
+useCase:
+ - secure-api
+ - call-api
---
# Dynamic Client Registration
-<%= include('../_includes/_pipeline2') %>
-
-Dynamic Client Registration enables you to register clients dynamically. These clients can be either [first-party or third-party clients](/clients/client-types#first-vs-third-party-clients).
+Dynamic Client Registration enables you to register [third-party applications](/applications/guides/enable-third-party-apps) dynamically.
This feature is based on the [OpenID Connect Dynamic Client Registration specification](https://openid.net/specs/openid-connect-registration-1_0.html) and in this article we will see how you can enable and use it.
## Enable dynamic registration
-By default, the feature is disabled for all tenants. To change this, you have to:
-
-- update your tenant settings
-- promote the connections you will use with your dynamic clients to **domain connections**, and
-- update your client's login page (if you use [Lock](/libraries/lock/v11))
-
::: warning
-Auth0 supports **Open Dynamic Registration**, which means that if you enable this feature, **anyone** will be able to create clients in your tenant without a token.
+Auth0 supports **Open Dynamic Registration**, which means that if you enable this feature, **anyone** will be able to create applications in your tenant without a token.
:::
-### Update tenant settings
-
-Set the `enable_dynamic_client_registration` flag to `true` in your tenant's settings.
+By default, the feature is disabled for all tenants. To change this, you have to set the `enable_dynamic_client_registration` flag to `true` in your tenant's settings.
-This can be done by enabling the **OIDC Dynamic Client Registration** toggle on your tenant's [Advanced Settings page](${manage_url}/#/tenant/advanced).
+This can be done by enabling the **OIDC Dynamic Application Registration** toggle on your tenant's [Advanced Settings page](${manage_url}/#/tenant/advanced).
Alternatively, you can update this flag using the [Update tenant settings endpoint](/api/management/v2#!/Tenants/patch_settings).
@@ -38,130 +33,61 @@ Alternatively, you can update this flag using the [Update tenant settings endpoi
"method": "PATCH",
"url": "https://${account.namespace}/api/v2/tenants/settings",
"headers": [
- { "name": "Content-Type", "value": "client/json" },
+ { "name": "Content-Type", "value": "application/json" },
{ "name": "Authorization", "value": "Bearer API2_ACCESS_TOKEN" },
{ "name": "Cache-Control", "value": "no-cache" }
],
"postData": {
- "mimeType": "client/json",
+ "mimeType": "application/json",
"text" : "{ \"flags\": { \"enable_dynamic_client_registration\": true } }"
}
}
```
-You need to update the `API2_ACCESS_TOKEN` with a valid token with the scope `update:tenant_settings`. See [How to get a Management APIv2 Token](/api/management/v2/tokens#how-to-get-a-management-apiv2-token) for details on how to do so.
-
-### Promote connections
-
-Clients registered via the [Dynamic Client Registration Endpoint](#register-your-client) can only authenticate users using connections flagged as **Domain Connections**. These connections will be open for any dynamic client to allow users to authenticate.
-
-You can promote a connection to domain level using the [Update a Connection endpoint](/api/management/v2#!/Connections/patch_connections_by_id).
-
-```har
-{
- "method": "PATCH",
- "url": "https://${account.namespace}/api/v2/connections/CONNECTION_ID",
- "headers": [
- { "name": "Content-Type", "value": "client/json" },
- { "name": "Authorization", "value": "Bearer API2_ACCESS_TOKEN" },
- { "name": "Cache-Control", "value": "no-cache" }
- ],
- "postData": {
- "mimeType": "client/json",
- "text" : "{ \"is_domain_connection\": true }"
- }
-}
-```
-
-Where:
-- `API2_ACCESS_TOKEN`: [Α valid Auth0 API2 token](/api/management/v2/tokens#how-to-get-a-management-apiv2-token) with the scope `update:connections`
-- `CONNECTION_ID`: Τhe Id of the connection to be promoted
-
-
-### Update the login page
-
-To use the Auth0's [Universal Login](/hosted-pages/login) with the Dynamic Client feature, you need to use at least version `10.7.x` of Lock, and set `__useTenantInfo: config.isThirdPartyClient` when instantiating Lock.
-
-Sample script:
-
-```html
-
-...
-
-```
+You need to update the `API2_ACCESS_TOKEN` with a valid token with the scope `update:tenant_settings`. See [Access Tokens for the Management API](/api/management/v2/tokens) for details on how to do so.
## Use dynamic registration
-In this section we will see how you can dynamically register and configure an client.
+In this section we will see how you can dynamically register and configure an application.
-### Register your client
+### Register your application
-In order to dynamically register an client with Auth0, you need to send an HTTP `POST` message to the Client Registration endpoint: `https://${account.namespace}/oidc/register`. Note that Auth0 supports **Open Dynamic Registration**, which means that the endpoint will accept a registration request without an [Access Token](/tokens/access-token).
+To dynamically register an application with Auth0, you need to send an HTTP `POST` message to the Application Registration endpoint: `https://${account.namespace}/oidc/register`. Note that Auth0 supports **Open Dynamic Registration**, which means that the endpoint will accept a registration request without an Access Token.
-To create an client with the name `My Dynamic Client` and the callback URLs `https://client.example.com/callback` and `https://client.example.com/callback2`, use the following snippet.
+To create an application with the name `My Dynamic application` and the callback URLs `https://application.example.com/callback` and `https://application.example.com/callback2`, use the following snippet.
```har
{
"method": "POST",
"url": "https://${account.namespace}/oidc/register",
"headers": [
- { "name": "Content-Type", "value": "client/json" }
+ { "name": "Content-Type", "value": "application/json" }
],
"postData": {
- "mimeType": "client/json",
- "text": "{\"client_name\":\"My Dynamic Client\",\"redirect_uris\": [\"https://client.example.com/callback\", \"https://client.example.com/callback2\"]}"
+ "mimeType": "application/json",
+ "text": "{\"client_name\":\"My Dynamic Application\",\"redirect_uris\": [\"https://application.example.com/callback\", \"https://application.example.com/callback2\"]}"
}
}
```
Where:
-- **client_name**: The name of the Dynamic Client to be created
+- **client_name**: The name of the Dynamic Application to be created
- **redirect_uris** (required): An array of URLs that Auth0 will deem valid to call at the end of an authentication flow
-Optionally, you can set a value for `token_endpoint_auth_method`, which can be `none` or `client_secret_post` (default value).
+Optionally, you can set a value for `token_endpoint_auth_method`, which can be `none` or `client_secret_post` (default value). Use `token_endpoint_auth_method: none` in the request payload if creating a SPA.
-The response includes the basic client information.
+The response includes the basic application information.
```json
HTTP/1.1 201 Created
-Content-Type: client/json
+Content-Type: application/json
{
- "client_name": "My Dynamic Client",
+ "client_name": "My Dynamic Application",
"client_id": "8SXWY6j3afl2CP5ntwEOpMdPxxy49Gt2",
"client_secret": "Q5O...33P",
"redirect_uris": [
- "https://client.example.com/callback",
- "https://client.example.com/callback2"
+ "https://application.example.com/callback",
+ "https://application.example.com/callback2"
],
"client_secret_expires_at": 0
}
@@ -169,20 +95,20 @@ Content-Type: client/json
Where:
- **client_id**: Unique client identifier. This is the ID you will use while configuring your apps to use Auth0. It is generated by the system and it cannot be modified.
-- **client_secret**: Alphanumeric 64-bit client secret. This value is used by clients to authenticate to the [token endpoint](/api/authentication#get-token) and for signing and validating [ID Tokens](/tokens/id-token).
-- **client_secret_expires_at**: Time at which the `client_secret` will expire. For Auth0 this value will always be zero (`0`) which means that the client never expires.
+- **client_secret**: Alphanumeric 64-bit client secret. This value is used by applications to authenticate to the [token endpoint](/api/authentication#get-token) and for signing and validating [ID Tokens](/tokens/concepts/id-tokens).
+- **client_secret_expires_at**: Time at which the `client_secret` will expire. For Auth0 this value will always be zero (`0`) which means that the application never expires.
-Make a note of the Client ID and Secret, as these are the most important pieces for executing [authentication](/client-auth) and [authorization](/api-auth) flows.
+Make a note of the Client ID and Secret, as these are the most important pieces for executing [authentication](/application-auth) and [authorization](/api-auth) flows.
-Also, keep in mind that third-party developers are not allowed to modify the client settings. In case this is necessary, they need to contact the tenant owner with their request.
+Also, keep in mind that third-party developers are not allowed to modify the application settings. In case this is necessary, they need to contact the tenant owner with their request.
-### Configure your client
+### Configure your application
-Now that you have a Client ID and Secret, you can configure your client to authenticate users with Auth0.
+Now that you have a Client ID and Secret, you can configure your application to authenticate users with Auth0.
-We will go through a simple example, that shows how to call an API from a client-side web app, using the [Implicit Grant](/api-auth/tutorials/implicit-grant). For a list of tutorials on how to authenticate and authorize users, based on your client type, see the [API Authorization](/api-auth) page.
+We will go through a simple example, that shows how to call an API from a client-side web app, using the [Implicit Flow](/flows/guides/implicit/call-api-implicit). For a list of tutorials on how to authenticate and authorize users, based on your application type, see the [API Authorization](/api-auth) page.
-First, you need to configure your client to send the user to the authorization URL:
+First, you need to configure your application to send the user to the authorization URL:
```text
https://${account.namespace}/authorize?
@@ -191,22 +117,22 @@ https://${account.namespace}/authorize?
response_type={RESPONSE_TYPE}&
client_id=${account.clientId}&
redirect_uri=${account.callback}&
- nonce={CRYPTOGRAPHIC_NONCE}
+ nonce={NONCE}
state={OPAQUE_VALUE}
```
Where:
-- **audience** (optional): The target API for which the Client Client is requesting access on behalf of the user. Set this parameter if you need API access.
+- **audience** (optional): The target API for which the Application is requesting access on behalf of the user. Set this parameter if you need API access.
- **scope** (optional): The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must conform to a namespaced format (see panel below for more info), or any scopes supported by the target API (for example, `read:contacts`). Set this parameter if you need API access.
::: panel Custom claims namespaced format
In order to add custom claims to ID Tokens or Access Tokens, they must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims) to avoid possible collisions with standard OpenID Connect claims. For example, if you choose the namespace `https://foo.com/` and you want to add a custom claim named `myclaim`, you would name the claim `https://foo.com/myclaim`, instead of `myclaim`.
:::
-- **response_type**: The response type. For Implicit Grant you can either use `token` or `id_token token`. This will specify the type of token you will receive at the end of the flow. Use `token` to get only an `access_token`, or `id_token token` to get both an `id_token` and an `access_token`.
-- **client_id**: Your client's Client ID.
-- **redirect_uri**: The URL to which the Authorization Server (Auth0) will redirect the User Agent (Browser) after authorization has been granted by the User. The `access_token` (and optionally an `id_token`) will be available in the hash fragment of this URL. This URL must be specified as a valid callback URL under the Client Settings of your client.
-- **state**: An opaque value the clients add to the initial request that the authorization server includes when redirecting the back to the client. This value must be used by the client to prevent CSRF attacks.
+- **response_type**: The response type. For Implicit Grant you can either use `token` or `id_token token`. This will specify the type of token you will receive at the end of the flow. Use `token` to get only an Access Token, or `id_token token` to get both an ID Token and an Access Token.
+- **client_id**: Your application's Client ID.
+- **redirect_uri**: The URL to which the Authorization Server (Auth0) will redirect the User Agent (Browser) after authorization has been granted by the User. The Access Token (and optionally an ID Token) will be available in the hash fragment of this URL. This URL must be specified as a valid callback URL under the Application Settings of your application.
+- **state**: An opaque value the applications add to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks.
- **nonce**: A string value which will be included in the ID Token response from Auth0, [used to prevent token replay attacks](/api-auth/tutorials/nonce). It is required for `response_type=id_token token`.
For example:
@@ -217,6 +143,6 @@ For example:
```
-This call will redirect the user to Auth0, and upon successful authentication, back to your client (specifically to the **redirect_uri**).
+This call will redirect the user to Auth0, and upon successful authentication, back to your application (specifically to the **redirect_uri**).
-If you need API access, then following the authentication, you need to [extract the Access Token](/api-auth/tutorials/implicit-grant#2-extract-the-access-token) from the hash fragment of the URL, and use it to make calls to the API, by passing it as a `Bearer` token in the `Authorization` header of the HTTP request.
+If you need API access, then following the authentication, you need to extract the Access Token from the hash fragment of the URL, and use it to make calls to the API, by passing it as a `Bearer` token in the `Authorization` header of the HTTP request.
diff --git a/articles/api-auth/faq.md b/articles/api-auth/faq.md
index cf2c3592ba..d5fea1d7e6 100644
--- a/articles/api-auth/faq.md
+++ b/articles/api-auth/faq.md
@@ -1,22 +1,28 @@
---
description: API Authentication and Authorization FAQ
+topics:
+ - api-authentication
+ - oidc
+ - user-consent
+ - resource-servers
+ - applications
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
# API Authentication and Authorization FAQ
-## Can I execute a user consent flow?
-
-Yes! We are working on creating documentation and tutorials for implementing this flow. In the meantime, if you need assistance or more information please contact our [Support Center](${env.DOMAIN_URL_SUPPORT}).
-
## I have an Application that needs to talk to different Resource Servers
-If a single Application needs Access Tokens for different resource servers, then multiple calls to `/authorize` (that is, multiple executions of the same or different Authorization Flow) needs to be performed. Each authorization will use a different value for `audience`, which will result in a different Access Token at the end of the flow.
+If a single Application needs Access Tokens for different resource servers, then multiple calls to `/authorize` (that is, multiple executions of the same or different Authorization Flow) needs to be performed. Each authorization will use a different value for `audience`, which will result in a different Access Token at the end of the flow.
For more information, see the [OAuth 2.0: Audience Information Specification](https://tools.ietf.org/html/draft-tschofenig-oauth-audience-00#section-3).
## Can I try the endpoints before I implement my application?
-**A** Sure! You have two options:
+Sure! You have two options:
- [Download our Postman collection](https://app.getpostman.com/run-collection/2a9bc47495ab00cda178). For more information on how to use our Postman collection refer to [Using the Auth0 API with our Postman Collections](/api/postman).
- Use our [Authentication API Debugger Extension](/extensions/authentication-api-debugger). You can find detailed instructions per endpoint/grant at our [Authentication API Reference](/api/authentication).
diff --git a/articles/api-auth/grant/authorization-code-pkce.md b/articles/api-auth/grant/authorization-code-pkce.md
index 770fbfe1c2..fb575ab2c1 100644
--- a/articles/api-auth/grant/authorization-code-pkce.md
+++ b/articles/api-auth/grant/authorization-code-pkce.md
@@ -1,11 +1,17 @@
---
-description: Describes the call APIs from mobile apps using the Authentication Code Grant (PKCE).
+description: Describes the call APIs from mobile apps using the Authentication Code Grant (PKCE).
+topics:
+ - authorization-code
+ - pkce
+ - api-authorization
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Calling APIs from Mobile Apps
+# Call APIs from Mobile Apps
-<%= include('../../_includes/_pipeline2') %>
-
-In order to access an API from a [mobile app](/quickstart/native), you need to implement the **Authorization Code using Proof Key for Code Exchange (PKCE)** OAuth 2.0 grant. In this document we will see how this flow works.
+To access an API from a [mobile app](/quickstart/native), you need to implement the **Authorization Code using Proof Key for Code Exchange (PKCE)** OAuth 2.0 grant. In this document, we will see how this flow works.
::: note
If you need a refresher on the OAuth 2.0 protocol, you can go through our [OAuth 2.0](/protocols/oauth2) article.
@@ -13,7 +19,7 @@ If you need a refresher on the OAuth 2.0 protocol, you can go through our [OAuth
## Overview of the flow
-The [Authorization Code Grant](/api-auth/grant/authorization-code) has some security issues, when implemented on native applications. For instance, a malicious attacker can intercept the `authorization_code` returned by Auth0 and exchange it for an [Access Token](/tokens/access-token) (and possibly a [Refresh Token](/tokens/refresh-token)).
+The [Authorization Code Grant](/api-auth/grant/authorization-code) has some security issues when implemented on native applications. For instance, a malicious attacker can intercept the `authorization_code` returned by Auth0 and exchange it for an Access Token (and possibly a Refresh Token).
The **Proof Key for Code Exchange (PKCE)** (defined in [RFC 7636](https://tools.ietf.org/html/rfc7636)) is a technique used to mitigate this authorization code interception attack.
@@ -21,18 +27,18 @@ With PKCE, the application creates, for every authorization request, a cryptogra

- 1. The native app initiates the flow and redirects the user to Auth0 (specifically to the [/authorize endpoint](/api/authentication#authorization-code-grant-pkce-)), sending the `code_challenge` and `code_challenge_method` parameters.
+ 1. The native application initiates the flow and redirects the user to Auth0 (specifically to the [/authorize endpoint](/api/authentication#authorization-code-grant-pkce-)), sending the `code_challenge` and `code_challenge_method` parameters.
- 2. Auth0 redirects the user to the native app with an `authorization_code` in the querystring.
+ 2. Auth0 redirects the user to the native application with an `authorization_code` in the querystring.
- 3. The native app sends the `authorization_code` and `code_verifier` together with the `redirect_uri` and the `client_id` to Auth0. This is done using the [/oauth/token endpoint](/api/authentication?http#authorization-code-pkce-).
+ 3. The native application sends the `authorization_code` and `code_verifier` together with the `redirect_uri` and the `client_id` to Auth0. This is done using the [/oauth/token endpoint](/api/authentication?http#authorization-code-pkce-).
- 4. Auth0 validates this information and returns an `access_token` (and optionally a `refresh_token`).
+ 4. Auth0 validates this information and returns an Access Token (and optionally a Refresh Token).
- 5. The native app can use the `access_token` to call the API on behalf of the user.
+ 5. The native application can use the Access Token to call the API on behalf of the user.
::: note
-In OAuth 2.0 terms, the native app is the Client, the end user the Resource Owner, the API the Resource Server, the browser the User Agent, and Auth0 the Authorization Server.
+In OAuth 2.0 terms, the native application is the Client, the end user the Resource Owner, the API the Resource Server, the browser the User Agent, and Auth0 the Authorization Server.
:::
## How to implement the flow
@@ -50,7 +56,6 @@ For details on how to implement this, refer to [Execute an Authorization Code Gr
::: next-steps
- [Execute an Authorization Code Grant Flow with PKCE](/api-auth/tutorials/authorization-code-grant-pkce)
- [How to configure an API in Auth0](/apis)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
+- [Tokens](/tokens)
- [Application Authentication for Mobile & Desktop Apps](/application-auth/mobile-desktop)
-- [Tokens used by Auth0](/tokens)
:::
diff --git a/articles/api-auth/grant/authorization-code.md b/articles/api-auth/grant/authorization-code.md
index 031086debd..45412c6e0b 100644
--- a/articles/api-auth/grant/authorization-code.md
+++ b/articles/api-auth/grant/authorization-code.md
@@ -1,9 +1,14 @@
---
-description: Describes how to call APIs from regular web apps using the Authentication Code Grant.
+description: Describes how to call APIs from regular web apps using the Authentication Code Grant.
+topics:
+ - authorization-code
+ - api-authorization
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Calling APIs from Server-side Web Apps
-
-<%= include('../../_includes/_pipeline2') %>
+# Call APIs from Server-side Web Apps
In order to access an API from a [regular web app](/quickstart/webapp), you need to implement the **Authorization Code** OAuth 2.0 grant. In this document we will see how this flow works.
@@ -13,21 +18,21 @@ If you need a refresher on the OAuth 2.0 protocol, you can go through our [OAuth
## Overview of the flow
-The **Authorization Code Grant** (defined in [RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)) is a flow where the browser receives an Authorization Code from Auth0 and sends this to the web app. The web app will then interact with Auth0 and exchange the Authorization Code for an [access_token](/tokens/access-token), and optionally an [id_token](/tokens/id-token) and a [refresh_token](/tokens/refresh_token). The web app can now use this `access_token` to call the API on behalf of the user.
+The **Authorization Code Grant** (defined in [RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)) is a flow where the browser receives an Authorization Code from Auth0 and sends this to the web app. The web app will then interact with Auth0 and exchange the Authorization Code for an [Access Token](/tokens/concepts/access-tokens), and optionally an [ID Token](/tokens/concepts/id-tokens) and a Refresh Token. The web app can now use this Access Token to call the API on behalf of the user.

1. The web app initiates the flow and redirects the browser to Auth0 (specifically to the [/authorize endpoint](/api/authentication#authorization-code-grant)), so the user can authenticate.
-1. Auth0 authenticates the user (via the browser). The first time the user goes through this flow a consent page will be shown where the permissions are listed that will be given to the applicaion (for example: post messages, list contacts, and so forth).
+1. Auth0 authenticates the user (via the browser). The first time the user goes through this flow a consent page will be shown where the permissions are listed that will be given to the application (for example: post messages, list contacts, and so forth).
1. Auth0 redirects the user to the web app (specifically to the `redirect_uri`, as specified in the [/authorize request](/api/authentication#authorization-code-grant)) with an Authorization Code in the querystring (`code`).
-1. The web app sends the Authorization Code to Auth0 and asks to exchange it with an `access_token` (and optionally an `id_token` and a `refresh_token`). This is done using the [/oauth/token endpoint](/api/authentication?http#authorization-code). When making this request, the web app authenticates with Auth0, using the Client Id and Client Secret.
+1. The web app sends the Authorization Code to Auth0 and asks to exchange it with an Access Token (and optionally an ID Token and a Refresh Token). This is done using the [/oauth/token endpoint](/api/authentication?http#authorization-code). When making this request, the web app authenticates with Auth0, using the Client Id and Client Secret.
1. Auth0 authenticates the web app, validates the Authorization Code and responds back with the token.
-1. The web app can use the `access_token` to call the API on behalf of the user.
+1. The web app can use the Access Token to call the API on behalf of the user.
::: note
In OAuth 2.0 terms, the web app is the application, the end user the Resource Owner, the API the Resource Server, the browser the User Agent, and Auth0 the Authorization Server.
@@ -49,7 +54,6 @@ For details on how to implement this, refer to [Execute an Authorization Code Gr
::: next-steps
- [How to implement an Authorization Code Grant flow](/api-auth/tutorials/authorization-code-grant)
- [How to configure an API in Auth0](/apis)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
+- [Tokens](/tokens)
- [Application Authentication for Server-side Web Apps](/application-auth/server-side-web)
-- [Tokens used by Auth0](/tokens)
:::
diff --git a/articles/api-auth/grant/client-credentials.md b/articles/api-auth/grant/client-credentials.md
index fe6b1df851..8fa8cd26d3 100644
--- a/articles/api-auth/grant/client-credentials.md
+++ b/articles/api-auth/grant/client-credentials.md
@@ -1,42 +1,42 @@
---
description: Describes how to call APIs from server processes using the Client Credentials Grant.
+topics:
+ - client-credentials
+ - api-authorization
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Calling APIs from a Service
+# Client Credentials Grant
-<%= include('../../_includes/_pipeline2') %>
+The **Client Credentials Grant** (defined in [RFC 6749, section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)) allows an application to request an Access Token using its __Client Id__ and __Client Secret__. It is used for non interactive applications (a CLI, a daemon, or a Service running on your backend) where the token is issued to the application itself, instead of an end user.
-The OAuth 2.0 grant that machine-to-machine interfaces utilize in order to access an API, is the **Client Credentials Grant**. In this document we will see how this flow works.
+In order to be able to perform the Client Credentials Grant, the Application needs to have the [Client Credentials grant type](/applications/concepts/application-grant-types) enabled. Machine to Machine Applications and Regular Web Applications have it enabled by default.
-::: note
-If you need a refresher on the OAuth 2.0 protocol, you can go through our [OAuth 2.0](/protocols/oauth2) article.
-:::
-
-## Overview of the flow
-
-With **Client Credentials Grant** (defined in [RFC 6749, section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)) a Non Interactive Client (a CLI, a daemon, or a Service running on your backend), can directly ask Auth0 for an `access_token`, by using its Client Credentials (__Client Id__ and __Client Secret__) to authenticate. In this case the token represents the Non Interactive Client itself, instead of an end user.
+## Client Credentials Grant Flow

1. The application authenticates with Auth0 using its __Client Id__ and __Client Secret__.
-1. Auth0 validates this information and returns an `access_token`.
+1. Auth0 validates this information and returns an Access Token.
-1. The application can use the `access_token` to call the API on behalf of itself.
+1. The application can use the Access Token to call the API on behalf of itself.
::: note
-In OAuth 2.0 terms, the non interactive app is the Client, the end user the Resource Owner, the API the Resource Server, the browser the User Agent, and Auth0 the Authorization Server.
+In OAuth 2.0 terms, the application is the Client, the end user the Resource Owner, the API the Resource Server, the browser the User Agent, and Auth0 the Authorization Server.
:::
## How to implement the flow
-For details on how to implement this using Auth0, refer to [Execute a Client Credentials Grant](/api-auth/tutorials/client-credentials). Before you do so, you have to set up the Grant first either [using the Dashboard](/api-auth/config/using-the-auth0-dashboard) or [using the Management API](/api-auth/config/using-the-management-api).
+For details on how to implement this using Auth0, refer to [Execute a Client Credentials Grant](/api-auth/tutorials/client-credentials).
## Keep reading
::: next-steps
- [How to implement a Client Credentials flow](/api-auth/tutorials/client-credentials)
- [How to configure an API in Auth0](/apis)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
+- [Tokens](/tokens)
- [How to change the scopes and add custom claims to the tokens using Hooks](/api-auth/tutorials/client-credentials/customize-with-hooks)
-- [Tokens used by Auth0](/tokens)
:::
diff --git a/articles/api-auth/grant/hybrid.md b/articles/api-auth/grant/hybrid.md
new file mode 100644
index 0000000000..496e658d8b
--- /dev/null
+++ b/articles/api-auth/grant/hybrid.md
@@ -0,0 +1,66 @@
+---
+description: Describes how to call APIs from applications using the Hybrid Flow
+public: false
+topics:
+ - authorization-code
+ - api-authorization
+ - implicit
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
+---
+# Call APIs Using the Hybrid Flow
+
+The Hybrid Flow is an OpenID Connect (OIDC) flow that draws from the following:
+
+1. [Authorization Code Flow](/flows/concepts/auth-code)
+2. [Implicit Flow](/flows/concepts/implicit)
+
+The Hybrid Flow enables use cases where your application can immediately use an ID token to access information about the user while obtaining an authorization code that can be exchanged for an Access Token (therefore gaining access to protected resources for an extended period of time).
+
+## Background
+
+With the [Authorization Code Flow](/flows/concepts/auth-code), Auth0 sends you an authorization code, which your app then sends in to retrieve tokens. Your application authenticates itself with a Client ID and Client Secret stored securely on your server.
+
+On the other hand, the [Implicit Flow](/flows/concepts/implicit) allows you to request Access Tokens without needing to authenticate your application. Auth0 verifies your app's identity based on the provided redirect URI. Because of this, you shouldn't utilize long-lived Access Tokens, and you cannot use Refresh Tokens.
+
+## The Hybrid Flow
+
+The Hybrid Flow allows you to take advantage of aspects of both the Authorization Code and Implicit Grants. For each interaction with Auth0, you will receive two (sometimes three) items in response:
+
+1. An authorization code and an Access Token
+1. An authorization code and an ID Token
+1. An authorization code, an Access Token, and an ID Token
+
+In this article, we will take a closer look at how this flow works.
+
+## Overview of the flow
+
+1. The web application initiates the authorization flow and redirects the browser to Auth0 (specifically, the [Authorization Endpoint](/api/authentication#authorization-code-grant)) so that the user can authenticate.
+
+1. Auth0 authenticates the user via the browser. If this is the first time the user does this, they will see a consent page listing the permissions that Auth0 will give to the application.
+
+1. Auth0 redirects the user to the app with an [Access Token](/tokens/access-token) and (optionally) an [ID Token](/tokens/concepts/id-tokens) in the hash fragment of the URI. The app can now extract the tokens from the hash fragment.
+
+1. The application parses out the Authorization Code, sends it to Auth0's [token endpoint](/api/authentication?http#authorization-code), and requests that Auth0 return (in exchange) the Access Token. The application identifies itself during this request using its assigned Client ID and Client Secret.
+
+1. If the request sent to the token endpoint is valid, Auth0 responds to the application's request with an ID Token, as well as an Access Token (and possibly a Refresh Token).
+
+1. The application can now validate the ID Token and retrieve the end user's information. The application can also use the Access Token to call desired APIs.
+
+ If the application received an ID Token from the Authorization endpoint already, it should have validated the token's signature, `c_hash`, and any other claims as defined. You must validate such tokens [the way you would for an Implicit Flow](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitIDTValidation).
+
+## How to implement the flow
+
+For details on how to implement this using Auth0, refer to [Execute the Hybrid Flow](/api-auth/tutorials/hybrid-flow).
+
+## Keep reading
+
+::: next-steps
+- [Execute the Hybrid Flow](/api-auth/tutorials/hybrid-flow)
+- [How to configure an API in Auth0](/apis)
+- [Tokens](/tokens)
+- [Application authentication for regular web apps](/flows/concepts/auth-code)
+- [Application authentication for single-page apps](/flows/concepts/implicit)
+:::
\ No newline at end of file
diff --git a/articles/api-auth/grant/implicit.md b/articles/api-auth/grant/implicit.md
index 65762fd8fd..bf1a08f84c 100644
--- a/articles/api-auth/grant/implicit.md
+++ b/articles/api-auth/grant/implicit.md
@@ -2,12 +2,17 @@
title: Call APIs from Client-side Web Apps
description: Learn how to call APIs from client-side web apps using the OAuth 2.0 Implicit Grant.
toc: true
+topics:
+ - implicit
+ - api-authorization
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
# Call APIs from Client-side Web Apps
-<%= include('../../_includes/_pipeline2') %>
-
-In order to access an API from a [client-side app](/quickstart/spa) (typically a Single Page Application or a Mobile Application), you need to implement the OAuth 2.0 **Implicit Grant**. In this document we will see how this flow works.
+In order to access an API from a [client-side app](/quickstart/spa) (typically a Single-Page Application or a Mobile Application), you need to implement the OAuth 2.0 **Implicit Grant**. In this document we will see how this flow works.
::: note
If you need a refresher on the OAuth 2.0 protocol, you can go through our [OAuth 2.0](/protocols/oauth2) article.
@@ -15,9 +20,9 @@ If you need a refresher on the OAuth 2.0 protocol, you can go through our [OAuth
## Overview
-The **Implicit Grant** (defined in [RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.2)) is similar to the [Authorization Code Grant](/api-auth/grant/authorization-code), but the main difference is that the application receives an [access_token](/tokens/access-token) directly, without the need for an `authorization_code`. This happens because the application, which is typically a JavaScript app running within a browser, is less trusted than a web app running on the server, hence cannot be trusted with the `client_secret` (which is required in the [Authorization Code Grant](/api-auth/grant/authorization-code)). Also, in the Implicit Grant, no Refresh Tokens are returned for the same reason (for an alternative refer to [Silent authentication for SPAs](/api-auth/tutorials/silent-authentication)).
+The **Implicit Grant** (defined in [RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.2)) is similar to the [Authorization Code Grant](/api-auth/grant/authorization-code), but the main difference is that the application receives an [Access Token](/tokens/concepts/access-tokens) directly, without the need for an `authorization_code`. This happens because the application, which is typically a JavaScript app running within a browser, is less trusted than a web app running on the server, hence cannot be trusted with the `client_secret` (which is required in the [Authorization Code Grant](/api-auth/grant/authorization-code)). Also, in the Implicit Grant, no Refresh Tokens are returned for the same reason (for an alternative refer to [Silent authentication for SPAs](/api-auth/tutorials/silent-authentication)).
-Once the user authenticates, the application receives the `access_token` in the hash fragment of the URI. The application can now use this `access_token` to call the API on behalf of the user.
+Once the user authenticates, the application receives the Access Token in the hash fragment of the URI. The application can now use this Access Token to call the API on behalf of the user.

@@ -25,9 +30,9 @@ Once the user authenticates, the application receives the `access_token` in the
1. Auth0 authenticates the user. The first time the user goes through this flow a consent page will be shown where the permissions, that will be given to the Application, are listed (for example: post messages, list contacts, and so forth).
- 1. Auth0 redirects the user to the app with an [access_token](/tokens/access-token) (and optionally an [id_token](/tokens/id-token)) in the hash fragment of the URI. The app can now extract the tokens from the hash fragment. In a Single Page Application (SPA) this would be done using Javascript and in a Mobile Application this is typically handled by interacting with a Web View.
+ 1. Auth0 redirects the user to the app with an [Access Token](/tokens/concepts/access-tokens) (and optionally an [ID Token](/tokens/concepts/id-tokens)) in the hash fragment of the URI. The app can now extract the tokens from the hash fragment. In a Single-Page Application (SPA) this would be done using Javascript and in a Mobile Application this is typically handled by interacting with a Web View.
- 1. The app can use the `access_token` to call the API on behalf of the user.
+ 1. The app can use the Access Token to call the API on behalf of the user.
::: note
In OAuth 2.0 terms, the web app is the Application, the end user the Resource Owner, the API the Resource Server, the browser the User Agent, and Auth0 the Authorization Server.
@@ -45,7 +50,7 @@ For details on how to implement this, refer to [How to implement the Implicit Gr
## Silent Authentication
-If you need to authenticate your users without a login page (for example, when the user is already logged in via [SSO](/sso) scenario) or get a new `access_token` (thus simulate refreshing an expired token), you can use Silent Authentication.
+If you need to authenticate your users without a login page (for example, when the user is already logged in via [Single Sign-on (SSO)](/sso) scenario) or get a new Access Token (thus simulate refreshing an expired token), you can use Silent Authentication.
For details on how to implement this, refer to [Silent Authentication](/api-auth/tutorials/silent-authentication).
@@ -55,6 +60,6 @@ For details on how to implement this, refer to [Silent Authentication](/api-auth
* [How to implement the Implicit Grant](/api-auth/tutorials/implicit-grant)
* [How to protect your SPA against replay attacks](/api-auth/tutorials/nonce)
* [How to configure an API in Auth0](/apis)
-* [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
+* [Tokens](/tokens)
* [Application Authentication for Client-side Web Apps](/application-auth/client-side-web)
:::
diff --git a/articles/api-auth/grant/password.md b/articles/api-auth/grant/password.md
index 82597c5860..3da4c9a514 100644
--- a/articles/api-auth/grant/password.md
+++ b/articles/api-auth/grant/password.md
@@ -1,33 +1,29 @@
---
title: Call APIs from Highly Trusted Applications
description: Describes how to call APIs from highly trusted applications using the Resource Owner Password Grant.
+topics:
+ - implicit
+ - api-authorization
+ - resource-owner-password
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
# Call APIs from Highly Trusted Applications
-<%= include('../../_includes/_pipeline2') %>
+<%= include('../_includes/_ropg-warning') %>
-Highly trusted applications can use this flow to access APIs. In this flow the end-user is asked to fill in credentials (username/password), typically using an interactive form. This information is sent to the backend and from there to Auth0.
+You can use the ROPG flow for your highly trusted applications to access APIs. In this flow the end-user is asked to fill in credentials (username/password), typically using an interactive form. This information is sent to the backend and from there to Auth0.
-You should use this flow **only if** the following apply:
-- The application is absolutely trusted with the user's credentials. For [client side](/api-auth/grant/implicit) applications and [mobile apps](/api-auth/grant/authorization-code-pkce) we recommend using web flows instead.
-- Using a redirect-based flow is not possible. If this is not the case and redirects are possible in your application you should use the [Authorization Code Grant](/api-auth/grant/authorization-code) instead.
-
-::: note
-If you need a refresher on the OAuth 2.0 protocol, you can go through our [OAuth 2.0](/protocols/oauth2) article.
-:::
-
-## Overview
-
-The **Resource Owner Password Grant** (defined in [RFC 6749, section 4.3](https://tools.ietf.org/html/rfc6749#section-4.3)) can be used directly as an authorization grant to obtain an Access Token, and optionally a Refresh Token. This grant should only be used when there is a high degree of trust between the user and the application and when other authorization flows are not available.
-
-This grant type can eliminate the need for the application to store the user credentials for future use, by exchanging the credentials with a long-lived Access Token or Refresh Token.
+ROPG (defined in [RFC 6749, section 4.3](https://tools.ietf.org/html/rfc6749#section-4.3)) can be used directly as an authorization grant to store the user credentials for future use, by exchanging the credentials for an Access Token, and optionally a Refresh Token.

1. The end user enters the credentials into the application.
1. The application forwards the credentials to Auth0.
- 1. Auth0 validates the information and returns an `access_token`, and optionally a `refresh_token`.
- 1. The application can use the `access_token` to call the API on behalf of the end user.
+ 1. Auth0 validates the information and returns an Access Token, and optionally a Refresh Token.
+ 1. The application can use the Access Token to call the API on behalf of the end user.
::: note
In OAuth 2.0 terms, the web app is the Client, the end user the Resource Owner, the API the Resource Server, the browser the User Agent, and Auth0 the Authorization Server.
@@ -35,9 +31,9 @@ In OAuth 2.0 terms, the web app is the Client, the end user the Resource Owner,
## How to implement the flow
-For details on how to implement this using Auth0, refer to [Execute the Resource Owner Password Grant](/api-auth/tutorials/password-grant).
+For details on how to implement this using Auth0, see [Implement the Resource Owner Password Grant](/api-auth/tutorials/password-grant).
-## Realm Support
+## Realm support
A extension grant that offers similar functionality with the **Resource Owner Password Grant**, including the ability to indicate a specific realm, is the `http://auth0.com/oauth/grant-type/password-realm`.
@@ -47,7 +43,7 @@ For more information on how to implement this extension grant refer to [Executin
## Scopes
-Due to the implied trust in these grants (a user providing his or her password to an application), the `access_token` returned will include all of the available scopes defined for the audience API. An application can request a restricted set of scopes by using the `scope` parameter, or you can restrict the returned scopes by using a [rule](#customize-the-returned-token).
+Due to the implied trust in these grants (a user providing his or her password to an application), the Access Token returned will include all of the available scopes defined for the audience API. An application can request a restricted set of scopes by using the `scope` parameter, or you can restrict the returned scopes by using a [rule](#customize-the-returned-token).
## Rules
@@ -57,17 +53,15 @@ Due to the implied trust in these grants (a user providing his or her password t
If you wish to execute special logic unique to the Password exchange, you can look at the `context.protocol` property in your rule. If the value is `oauth2-password`, then the rule is running during the password exchange.
-For details on how to implement this, refer to [Execute the Resource Owner Password Grant: Customize the Tokens](/api-auth/tutorials/password-grant#optional-customize-the-tokens).
+For details on how to implement this, see [Customize the Tokens](/api-auth/tutorials/password-grant#optional-customize-the-tokens).
-## MFA Support
+## MFA support and anomaly detection
-For details on how to implement multifactor authentication, refer to [Multifactor Αuthentication and Resource Owner Password](/api-auth/tutorials/multifactor-resource-owner-password).
+For details on how to implement multi-factor authentication (MFA), refer to [Multi-factor Authentication and Resource Owner Password](/mfa/guides/mfa-api/multifactor-resource-owner-password).
+
+When using this flow from server-side applications, some anomaly detection features might fail because of the particularities of this scenario. For details on how to implement this, while avoiding some common issues, refer to [Using Resource Owner Password from Server side](/api-auth/tutorials/using-resource-owner-password-from-server-side).
## Keep reading
-::: next-steps
-* [How to Execute a Resource Owner Password Grant](/api-auth/tutorials/password-grant)
-* [How to use MFA with Resource Owner Password Grant](/api-auth/tutorials/multifactor-resource-owner-password)
-* [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
-* [How to use Resource Owner Password Grant from the server side together with Anomaly Detection](/api-auth/tutorials/using-resource-owner-password-from-server-side)
-:::
+* [Implement the Resource Owner Password Grant](/api-auth/tutorials/password-grant)
+* [Tokens](/tokens)
diff --git a/articles/api-auth/index.md b/articles/api-auth/index.md
index 778f80c4b4..2c2bdf84b6 100644
--- a/articles/api-auth/index.md
+++ b/articles/api-auth/index.md
@@ -3,6 +3,13 @@ url: /api-auth
section: articles
classes: topic-page
title: API Authorization
+topics:
+ - api-authentication
+ - oidc
+contentType: index
+useCase:
+ - secure-api
+ - call-api
---
@@ -13,31 +20,13 @@ title: API Authorization
-::: note
-Heads up! As part of our efforts to improve security and standards-based interoperability, we have implemented several new features in our authentication flows and made changes to existing ones. For an overview of these changes, and details on how you adopt them, refer to Introducing OIDC Conformant Authentication.
-:::
+At some point, your custom APIs will need to allow limited access to users, servers, or servers on behalf of users. With Auth0 you can manage the authorization requirements for server-to-server and application-to-server applications.
-At some point, your APIs will need to allow limited access to users, servers, or servers on behalf of users.
+By using the OAuth 2.0 authorization framework, you can give your own applications or third-party applications limited access to your APIs on behalf of the application itself. With Auth0, you can easily support different flows in your own APIs without worrying about the OAuth 2.0/OpenID Connect (OIDC) specification, or the many other technical aspects of API authorization.
-Auth0's API authorization features allow you to manage the authorization requirements for server-to-server and application-to-server applications.
-
-By using the OAuth 2.0 authorization framework, you can give your own applications or third-party applications limited access to your APIs on behalf of the application itself.
-
-Using Auth0, you can easily support different flows in your own APIs without worrying about the OAuth 2.0/OpenID Connect specification, or the many other technical aspects of API authorization.
+In this page you can find a list of resources that can help you secure your APIs and access them in a secure manner.
- This document presents an overview of the latest new features and changes in our authentication flows, explain why they were made and points to other detailed tutorials to help you adopt these changes.
-
If your application is a JavaScript-centric app executing on the browser, and you want to configure it to use OAuth 2.0 to access an API, read these docs.
- Learn about the differences between Αccess Τoken and ID Τoken and why the latter should never be used to secure an API.
+ Learn about the types of tokens related to identity and authentication and how they are used by Auth0.
@@ -154,15 +146,15 @@ Using Auth0, you can easily support different flows in your own APIs without wor
- Learn how to restrict users/applications from requesting API scopes for which they don't have access.
+ Learn how to restrict users/applications from accessing APIs.
@@ -172,9 +164,9 @@ Using Auth0, you can easily support different flows in your own APIs without wor
- Learn how to represent multiple APIs using a single Auth0 API.
+ Learn how to represent multiple APIs using a single logical API.
diff --git a/articles/api-auth/intro.md b/articles/api-auth/intro.md
index b2a027e8ae..77aa80441c 100644
--- a/articles/api-auth/intro.md
+++ b/articles/api-auth/intro.md
@@ -1,23 +1,29 @@
---
-title: Introducing OIDC Conformant Authentication
description: An overview of the OIDC Conformant authentication flows, why these changes were made and how you can adopt them.
toc: true
+topics:
+ - api-authentication
+ - oidc
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Introducing OIDC Conformant Authentication
+# OIDC-Conformant Authentication Overview
**Released Date**: May 10, 2017
-As part of our efforts to improve security and standards-based interoperability, we have implemented several new features in our authentication flows and made changes to existing ones. This document presents an overview of these changes, explain why they were made and point you to other detailed tutorials to help you adopt these changes.
+As part of our efforts to improve security and standards-based interoperability, we have implemented several new features in our authentication flows and made changes to existing ones. This document presents an overview of these changes, explains why they were made and points you to other detailed tutorials to help you adopt these changes.
-We will start by reviewing the [new features](#what-s-new), continue with [what changed](#what-is-changing) and how you can [distinguish which authentication flow is used](#how-to-use-the-new-flows) (the latest or the legacy). Towards the end of this doc, you can find a [summarizing table](#legacy-vs-new) and [links for further reading](#keep-reading).
+We will start by reviewing the [new features](#what-s-new), and then continue with [what changed](#what-is-changing) and how you can [distinguish which authentication flow is used](#how-to-use-the-new-flows) (the latest or the legacy). Towards the end of this doc, you can find a [summarizing table](#legacy-vs-new) and [links for further reading](#keep-reading).
## What should I read?
If you are new to Auth0, go through the [What’s New](#what-s-new) section of this doc. There you can find all the cool new features we introduced, like the ability to create APIs, call them from services, or enable external parties or partners to access protected resources at your API in a secure way. Then head off to the [How to use the new flows](#how-to-use-the-new-flows) section and make sure that your new implementation follows our latest, and more secure, authentication pipeline.
-If you are already using Auth0 in your app, you should read the complete doc. We have taken great care to make sure that we do not break our existing customers with this new OIDC conformant implementation, however you should be aware of all changes and new features, and how you can use them (or avoid doing so). It goes without saying that we strongly encourage you to adopt this authentication pipeline, to improve your app’s security.
+If you are already using Auth0 in your app, you should read the complete doc. We have taken great care to make sure that we do not break our existing customers with this new OIDC conformant implementation. However, you should be aware of all changes and new features, and how you can use them (or avoid doing so). It goes without saying that we strongly encourage you to adopt this authentication pipeline, to improve your app’s security.
-If you using Auth0 as a [SAML or WS-Federation identity provider](/protocols/saml/saml-idp-generic) to your application (that is, you're not using OIDC/OAuth), then you do not need to make any changes.
+If you are using Auth0 as a [SAML or WS-Federation identity provider](/protocols/saml/saml-idp-generic) for your application (that is, you're not using OIDC/OAuth), then you do not need to make any changes.
## What's New
@@ -45,19 +51,19 @@ So far, third-party applications cannot be created from the dashboard. They must
For more information, refer to [User consent and third-party applications](/api-auth/user-consent).
:::
-### Calling APIs from a Service (machine-to-machine)
+### Calling APIs from a Service (machine to machine)
-We implemented the OAuth 2.0 Client Credentials grant which allows applications to authenticate as themselves (that is, not on behalf of any user), in order to programatically and securely obtain access to an API.
+We implemented the OAuth 2.0 Client Credentials grant which allows applications to authenticate as themselves (that is, not on behalf of any user), in order to programmatically and securely obtain access to an API.
::: note
-For more information on the Client Credentials grant, refer to [Calling APIs from a Service](/api-auth/grant/client-credentials).
+For more information on the Client Credentials grant, refer to [How to Implement the Client Credentials Grant](/flows/guides/client-credentials/call-api-client-credentials).
:::
## What is Changing
### Calling APIs with Access Tokens
-Historically, protecting resources on your API has been accomplished using ID Tokens issued to your users after they authenticate in your applications. From now on, you should only use Access Tokens when calling APIs. ID Tokens should only be used by the application to verify that the user is authenticated and get basic user information. The main reason behind this change is security. For details on refer to [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis).
+Historically, protecting resources on your API has been accomplished using ID Tokens issued to your users after they authenticate in your applications. From now on, you should only use Access Tokens when calling APIs. ID Tokens should only be used by the application to verify that the user is authenticated and get basic user information. The main reason behind this change is security. For details, refer to [Tokens](/tokens).
::: note
For more information, refer to [Calling your APIs with Auth0 tokens](/api-auth/tutorials/adoption/api-tokens).
@@ -65,24 +71,24 @@ For more information, refer to [Calling your APIs with Auth0 tokens](/api-auth/t
### User Profile Claims and Scope
-Historically, you were able to define and request arbitrary application-specific claims. From now on, your application can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims), as [defined by the OIDC Specification](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims), or any scopes supported by your [API](/apis).
+Historically, you were able to define and request arbitrary application-specific claims. From now on, your application can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims), as [defined by the OIDC Specification](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims), or any scopes supported by your [API](/apis).
-In order to add custom claims to ID Tokens or Access Tokens, they must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims) to avoid possible collisions with standard OIDC claims.
+In order to add custom claims to ID Tokens or Access Tokens, they must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims.
-To customize the tokens, use Hooks for Client Credentials, and Rules for the rest of the grants:
-- __Client Credentials__: [Customize Tokens using Hooks](/api-auth/tutorials/client-credentials/customize-with-hooks)
-- __Resource Owner__: [Customize Tokens using Rules](/api-auth/grant/password#customizing-the-returned-tokens)
-- __Implicit Grant__: [Customize Tokens using Rules](/api-auth/tutorials/implicit-grant#optional-customize-the-tokens)
-- __Authorization Code__: [Customize Tokens using Rules](/api-auth/tutorials/authorization-code-grant#optional-customize-the-tokens)
-- __Authorization Code (PKCE)__: [Customize Tokens using Rules](/api-auth/tutorials/authorization-code-grant-pkce#optional-customize-the-tokens)
+To customize the tokens, use Hooks for the Client Credentials Flow, and Rules for the rest of the flows:
+- __Client Credentials Flow__: [Customize Tokens using Hooks](/flows/guides/client-credentials/call-api-client-credentials#customize-tokens)
+- __Trusted App Flow__: [Customize Tokens using Rules](/api-auth/grant/password#customizing-the-returned-tokens)
+- __Single-Page Flow__: [Customize Tokens using Rules](/flows/guides/implicit/call-api-auth-code-pkce#customize-tokens)
+- __Regular Web App Flow__: [Customize Tokens using Rules](/flows/guides/auth-code/call-api-auth-code#customize-tokens)
+- __Native/Mobile Flow__: [Customize Tokens using Rules](/flows/guides/auth-code-pkce/call-api-auth-code-pkce#customize-tokens)
::: note
For more information, refer to [User profile claims and scope](/api-auth/tutorials/adoption/scope-custom-claims).
:::
-### Single Sign On (SSO)
+### Single Sign-on (SSO)
-Initiating an SSO session must now happen __only__ from an Auth0-hosted page and not from applications. This means that for SSO to work, you must be using [universal login](/hosted-pages/login). Users must be redirected to the login page and then redirected to your application once authentication is complete.
+Initiating an Single Sign-on (SSO) session must now happen __only__ from an Auth0-hosted page and not from applications. This means that for SSO to work, you must be using Universal Login. Users must be redirected to the login page and then redirected to your application once authentication is complete.
::: note
Support for SSO from applications is planned for a future release.
@@ -99,15 +105,15 @@ Not all [OAuth 2.0 grants](/protocols/oauth2#authorization-grant-types) support
@@ -118,7 +124,7 @@ Not all [OAuth 2.0 grants](/protocols/oauth2#authorization-grant-types) support
::: note
-For more information, refer to [OIDC Single sign-on](/api-auth/tutorials/adoption/single-sign-on).
+For more information, refer to [OIDC Single Sign-on (SSO)](/api-auth/tutorials/adoption/single-sign-on).
:::
### Authorization Code Grant
@@ -127,8 +133,8 @@ Some changes were introduced in the implementation of Authorization Code grant:
- The `device` request parameter has been removed.
- The `audience` request parameter has been introduced. This denotes the target API for which the token should be issued.
-- The returned Access Token is a [JWT](/jwt), valid for calling the [/userinfo endpoint](/api/authentication#get-user-info) and the API specified by the `audience` parameter.
-- A Refresh Token will be returned only if the `offline_access` scope was granted.
+- The returned Access Token is a [JWT](/tokens/concepts/jwts), valid for calling the [/userinfo endpoint](/api/authentication#get-user-info) and the API specified by the `audience` parameter.
+- A Refresh Token will be returned only if the `offline_access` scope was granted.
::: note
For more information, refer to [Authorization Code grant](/api-auth/tutorials/adoption/authorization-code).
@@ -142,8 +148,8 @@ Some changes were introduced in the implementation of Implicit grant:
- The `audience` request parameter has been introduced. This denotes the target API for which the token should be issued.
- The `response_type` request parameter indicates whether we want to receive both an Access Token and ID Token. If using `response_type=id_token`, we will return only an ID Token.
- Refresh Tokens are not allowed. [Use `prompt=none` instead](/api-auth/tutorials/silent-authentication).
-- The `nonce` request parameter must be a [cryptographically secure random string](/api-auth/tutorials/nonce). After validating the ID Token, the application must [validate the nonce to mitigate replay attacks](/api-auth/tutorials/nonce). Requests made without a `nonce` parameter will be rejected.
-- The returned Access Token is a [JWT](/jwt), valid for calling the [/userinfo endpoint](/api/authentication#get-user-info) and the API specified by the `audience` parameter.
+- The `nonce` request parameter must be a [cryptographically-secure random string](/api-auth/tutorials/nonce). After validating the ID Token, the application must [validate the nonce to mitigate replay attacks](/api-auth/tutorials/nonce). Requests made without a `nonce` parameter will be rejected.
+- The returned Access Token is a [JWT](/tokens/concepts/jwts), valid for calling the [/userinfo endpoint](/api/authentication#get-user-info) and the API specified by the `audience` parameter.
- ID Tokens will be signed asymmetrically using `RS256`.
::: note
@@ -158,8 +164,8 @@ Some changes were introduced in the implementation of Resource Owner Password gr
- The `audience` request parameter has been introduced. This denotes the target API for which the token should be issued.
- The endpoint to execute token exchanges is [/oauth/token](/api/authentication#resource-owner-password).
- [Auth0's own grant type](/api-auth/tutorials/password-grant#realm-support) is used to authenticate users from a specific connection (`realm`). The [standard OIDC password grant](/api-auth/tutorials/password-grant) is also supported, but it does not accept Auth0-specific parameters such as `realm`.
-- The returned Access Token is a [JWT](/jwt), valid for calling the [/userinfo endpoint](/api/authentication#get-user-info) and the API specified by the `audience` parameter.
-- The ID Token will be forcibly signed using `RS256` if requested by a [public application](/applications/application-types#public-applications).
+- The returned Access Token is a [JWT](/tokens/concepts/jwts), valid for calling the [/userinfo endpoint](/api/authentication#get-user-info) and the API specified by the `audience` parameter.
+- The ID Token will be forcibly signed using `RS256` if requested by a [public application](/applications/concepts/app-types-confidential-public#public-applications).
- A Refresh Token will be returned only if the `offline_access` scope was granted.
::: note
@@ -168,6 +174,8 @@ For more information, refer to [Resource Owner Password Credentials exchange](/a
### Delegation
+<%= include('../_includes/_deprecate-delegation') %>
+
[Delegation](/api/authentication#delegation) is used for many operations:
- Exchanging an ID Token issued to one application for a new one issued to a different application
- Using a Refresh Token to obtain a fresh ID Token
@@ -175,13 +183,11 @@ For more information, refer to [Resource Owner Password Credentials exchange](/a
Given that [ID Tokens should no longer be used as API tokens](/api-auth/tutorials/adoption/api-tokens) and that [Refresh Tokens should be used only at the token endpoint](/api-auth/tutorials/adoption/refresh-tokens), this endpoint is now considered deprecated.
-At the moment there is no OIDC-compliant mechanism to obtain third-party API tokens. In order to facilitate a gradual migration to the new authentication pipeline, delegation can still be used to obtain third-party API tokens. This will be deprecated in future releases.
-
### Passwordless
-Our new implementation only supports an [OIDC-conformant](/api-auth/tutorials/adoption) passwordless authentication mechanism when using web applications (with Lock.js or auth0.js).
+Our new implementation only supports an [OIDC-conformant](/api-auth/tutorials/adoption) passwordless authentication mechanism when using web applications (with Lock.js or auth0.js).
-Native applications need to use Universal Login (with an Auth0-hosted login page). Customers can use the Lock (Passwordless) template in the [Dashboard](${manage_url}/#/login) under **Hosted Pages -> Login -> Default Templates**, or customize it to fit specific requirements.
+Native applications need to use Universal Login (with an Auth0-hosted login page). Customers can use the Lock (Passwordless) template in the [Dashboard](${manage_url}/#/login_settings) under **Universal Login -> Login -> Default Templates**, or customize it to fit specific requirements.
### Other Authentication API endpoints
@@ -198,7 +204,7 @@ Native applications need to use Universal Login (with an Auth0-hosted login page
To use the new pipeline, at least one of the following should apply:
- The application is flagged as __OIDC Conformant__, or
-- The `audience` parameter is set in the [/authorize](/api/authentication#authorize-client) or [/token](/api/authentication#get-token) endpoints
+- The `audience` parameter is set in the [/authorize](/api/authentication#authorize-application) or [/token](/api/authentication#get-token) endpoints
If none of these applies, then the legacy flows will be used.
@@ -206,7 +212,7 @@ To mark your application as OIDC Conformant: go to [Dashboard](${manage_url}) >

-To use the `audience` param instead, configure your app to send it when initiating an authorization request.
+To use the `audience` parameter instead, configure your app to send it when initiating an authorization request.
## Legacy vs New
@@ -242,12 +248,12 @@ To use the `audience` param instead, configure your app to send it when initiati
Not supported for Resource Owner grant. For the rest, universal login must be employed and users redirected to the login page.
+
Not supported for Resource Owner grant. For the rest, Universal Login must be employed and users redirected to the login page.
Access Token format
@@ -314,10 +320,8 @@ should be used instead with "grant_type": "refresh_token"
-## Keep Reading
+## Keep reading
-::: next-steps
* [API Authorization index](/api-auth)
-* [Why you should use Access Tokens to secure APIs?](/api-auth/why-use-access-tokens-to-secure-apis)
-* [Tokens used by Auth0](/tokens)
-:::
+* [Tokens](/tokens)
+
diff --git a/articles/api-auth/passwordless.md b/articles/api-auth/passwordless.md
index 8b3cda06bb..cc007bfeb4 100644
--- a/articles/api-auth/passwordless.md
+++ b/articles/api-auth/passwordless.md
@@ -1,14 +1,20 @@
---
title: Passwordless authentication (OIDC-conformant)
+topics:
+ - api-authentication
+ - oidc
+ - passwordless
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
# OIDC Conformant Passwordless Authentication
<%= include('./tutorials/adoption/_about.md') %>
-## About Passwordless Authentication
-
-Passwordless connections allow users to login without the need to remember a password.
+Passwordless connections allow users to login without the need to remember a password.
This improves the user experience, especially on mobile applications, since users will only need to remember an email address or phone number to authenticate with your application.
@@ -16,6 +22,6 @@ Without passwords, your application will not need to implement a password-reset
## OIDC Conformant Passwordless
-Auth0 currently supports [OIDC-conformant](/api-auth/tutorials/adoption) passwordless authentication using [universal login](/hosted-pages/login) as well as in embedded web authentication scenarios using the newest [Lock](/libraries/lock) or [Auth0.js](/libraries/auth0js) libraries.
+Auth0 currently supports [OIDC-conformant](/api-auth/tutorials/adoption) passwordless authentication using Universal Login as well as in embedded web authentication scenarios using the newest [Lock](/libraries/lock) or [Auth0.js](/libraries/auth0js) libraries.
-Native applications need to use universal login (with Auth0-hosted login page). Customers can use the Lock (Passwordless) template in the [Dashboard](${manage_url}) under **Hosted Pages > Default Templates**, or customize it to fit specific requirements.
+Native applications need to use Universal Login. Customers can use the Lock (Passwordless) template for the login page in the [Dashboard](${manage_url}) under **Universal Login > Login > Default Templates**, or customize the page to fit specific requirements.
diff --git a/articles/api-auth/restrict-access-api.md b/articles/api-auth/restrict-access-api.md
new file mode 100644
index 0000000000..ae857bd87b
--- /dev/null
+++ b/articles/api-auth/restrict-access-api.md
@@ -0,0 +1,83 @@
+---
+ title: Restrict Access to APIs
+ description: Learn how to write rules that will restrict user/application access to an API.
+ topics:
+ - api-authentication
+ - oidc
+ - scopes
+ - permissions
+contentType: how-to
+useCase:
+ - secure-api
+ - call-api
+---
+
+# Restrict Access to APIs
+
+Sometimes you may not want to allow an application or user to access an API. For example, you may want to restrict access to an API based on the calling application or a user's role or location. To do so, we use [rules](/rules).
+
+## Example: Deny access to anyone calling the API
+
+In this example, we want to deny access to all users who are calling the API. To do this, we create a [rule](/rules) to deny access depending on the `audience` parameter. In this case, the `audience` value for our API is `http:://todoapi2.api`, so this is the audience we will refuse.
+
+::: note
+The value of an API's `audience` is displayed in the **API Audience** field in the [APIs section of the Auth0 Dashboard](${manage_url}/#/apis).
+:::
+
+When a restricted user attempts to access the API, they will receive an `HTTP 401` response.
+
+```js
+function (user, context, callback) {
+
+ /*
+ * Denies access to user-based flows based on audience
+ */
+
+ var audience = '';
+
+ audience = audience
+ || (context.request && context.request.query && context.request.query.audience)
+ || (context.request && context.request.body && context.request.body.audience);
+
+ if (audience === 'http://todoapi2.api' || !audience) {
+ return callback(new UnauthorizedError('end_users_not_allowed'));
+ }
+
+ return callback(null, user, context);
+}
+```
+
+## Example: Deny access to users from a specific calling application
+
+In this example, we want to deny access to all users who are accessing the API from a specific calling application. To do this, we create a [rule](/rules) to deny access depending on the `client_id` parameter. This is equivalent to disabling all connections for an application.
+
+::: note
+The value of an application's `client_id` is displayed in the **Client ID** field in the [Applications section of the Auth0 Dashboard](${manage_url}/#/applications).
+:::
+
+When a restricted user attempts to access the API, they will receive an `HTTP 401` response.
+
+```js
+function (user, context, callback) {
+
+ /*
+ * Denies access to user-based flows based on client ID
+ */
+
+ var client_id = '';
+ client_id = context.clientID;
+
+ if (client_id === 'CLIENT_ID') {
+ return callback(new UnauthorizedError('end_users_not_allowed'));
+ }
+
+ return callback(null, user, context);
+}
+```
+## Example: Deny access to users based on a role
+
+By default, any user associated with an [Auth0 application](/applications) can request any [custom API scopes](/scopes/current/api-scopes) that have been created. Sometimes you may not want to allow a user to request certain scopes, though.
+
+To limit a user's scopes, you can assign them a role so that requests on their behalf are limited to just the scopes assigned to that role. To do this, you can use the [Authorization Extension](/extensions/authorization-extension) and a custom [Rule](/rules).
+
+We discuss this approach in more depth in our [SPA+API Architecture Scenario](/architecture-scenarios/spa-api). Specifically, you can review the [Configure the Authorization Extension](/architecture-scenarios/spa-api/part-2#configure-the-authorization-extension) section to learn how to configure the Authorization Extension and create a custom Rule that will ensure scopes are granted based on a user's role.
diff --git a/articles/api-auth/restrict-requests-for-scopes.md b/articles/api-auth/restrict-requests-for-scopes.md
deleted file mode 100644
index 42debc5963..0000000000
--- a/articles/api-auth/restrict-requests-for-scopes.md
+++ /dev/null
@@ -1,62 +0,0 @@
----
- description: Writing rules to restrict user/client access to an API
----
-
-# Restrict Application or User Requests for API Scopes
-
-By default, any user associated with an [Auth0 application](/applications) can request an API's [scope(s)](/scopes#api-scopes). If you would like to restrict access to the API's scopes based on the user's role, application association, location, and so on, you can do so via [rules](/rules). Then, if a restricted user attempts to request scopes not permitted to them, they will receive an `HTTP 401` response.
-
-## Example: Deny access based on the API audience
-
-The following [rule](/rules), demonstrates how you would deny access on an API, depending on the `audience` parameter. In this example, we deny access to all users, if the API they are trying to access has the `audience` set to `http://todoapi2.api`.
-
-```js
-function (user, context, callback) {
-
- /*
- * Denies access to user-based flows based on audience
- */
-
- var audience = '';
-
- audience = audience
- || (context.request && context.request.query && context.request.query.audience)
- || (context.request && context.request.body && context.request.body.audience);
-
- if (audience === 'http://todoapi2.api' || !audience) {
- return callback(new UnauthorizedError('end_users_not_allowed'));
- }
-
- return callback(null, user, context);
-}
-```
-
-::: note
-The value of an API's `audience` is displayed at the **API Audience** field, at [Dashboard > APIs](${manage_url}/#/apis).
-:::
-
-## Example: Deny access based on the Client ID
-
-The following [rule](/rules), demonstrates how you would deny access on an API, depending on the application the user is associated with. In this example, we deny access to all users, if the application through which they login, has an ID equal to `CLIENT_ID` (this is equivalent to disabling **all** Connections for the application).
-
-```js
-function (user, context, callback) {
-
- /*
- * Denies access to user-based flows based on client ID
- */
-
- var client_id = '';
- client_id = context.clientID;
-
- if (client_id === 'CLIENT_ID') {
- return callback(new UnauthorizedError('end_users_not_allowed'));
- }
-
- return callback(null, user, context);
-}
-```
-
-::: note
-The value of a client's Id is displayed at the **Client ID** field, at [Dashboard > Applications](${manage_url}/#/applications).
-:::
diff --git a/articles/api-auth/token-renewal-in-safari.md b/articles/api-auth/token-renewal-in-safari.md
new file mode 100644
index 0000000000..88742f553a
--- /dev/null
+++ b/articles/api-auth/token-renewal-in-safari.md
@@ -0,0 +1,56 @@
+---
+description: Issues with token renewal in Safari when ITP is enabled.
+topics:
+ - safari
+ - tokens
+ - token-renewal
+ - custom-domains
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
+---
+# Renew Tokens When Using Safari
+
+Renewing tokens with the `checkSession()` function does not work correctly with the latest version of the Safari browser.
+
+Recent versions of the Safari browser introduced a new featured called [Intelligent Tracking Prevention (ITP)](https://webkit.org/blog/category/privacy/). ITP is designed to prevent websites from tracking user activity across multiple websites.
+
+By default, ITP is active. You can determine if the Safari version you are using has ITP by going to **Preferences > Privacy** tab and seeing if the **Prevent cross-site tracking** option is checked.
+
+
+
+## ITP and browser behavior
+
+Enabling ITP causes the browser to behave as if you had disabled third-party cookies in the browser: **checkSession()** is unable to access the current user's session, which makes it impossible to obtain a new token without displaying anything to the user.
+
+This is akin to the way OpenID Connect (OIDC) uses iframes for handling [sessions](/sessions) in SPAs.
+
+## Workarounds
+
+Recent advancements in user privacy controls in browsers adversely impact the user experience by preventing access to third-party cookies. You can use [Refresh Token Rotation](/tokens/concepts/refresh-token-rotation) as an alternative that provides a secure method for using refresh tokens in SPAs while providing end-users with seamless access to resources without the disruption in UX caused by browser privacy technology like ITP.
+
+Alternatively, you can work around the issues posed by ITP by using Auth0's [custom domains](/custom-domains) functionality, particularly if the custom domain lives on a *subdomain* of the application's website domain. For example, if your application is hosted on **example.com**, the custom domain would need to be of the format **subdomain.example.com**.
+
+## ITP debug mode
+
+[Safari Technology Preview](https://developer.apple.com/safari/technology-preview/) offers an "Intelligent Tracking Prevention Debug Mode" that you can use to troubleshoot ITP issues. You can find instructions on how to debug ITP on [this blog post from WebKit](https://webkit.org/blog/8387/itp-debug-mode-in-safari-technology-preview-62/).
+
+**NOTE**: The instructions mention how to permanently classify a custom domain as having tracking abilities for testing purposes. In later versions of Safari Technology Preview, though, the domain to store the User Defaults for this setting changed from `com.apple.SafariTechnologyPreview` to `com.apple.WebKit.Networking`. If you are having trouble with the commands mentioned in the instructions, try these:
+
+* Classify a site as having tracking abilities:
+```
+defaults write com.apple.WebKit.Networking ResourceLoadStatisticsManualPrevalentResource example.com
+```
+
+* Inspect the setting:
+```
+defaults read com.apple.WebKit.Networking ResourceLoadStatisticsManualPrevalentResource
+```
+
+* Delete the setting:
+```
+defaults delete com.apple.WebKit.Networking ResourceLoadStatisticsManualPrevalentResource
+```
+
+You will need to restart Safari Technology Preview every time you make changes for the settings to take effect.
diff --git a/articles/api-auth/tutorials/adoption/_index.md b/articles/api-auth/tutorials/adoption/_index.md
index 63ca6e0e51..40760b5d79 100644
--- a/articles/api-auth/tutorials/adoption/_index.md
+++ b/articles/api-auth/tutorials/adoption/_index.md
@@ -1,14 +1,13 @@
-* [Calling your APIs with Auth0 tokens](/api-auth/tutorials/adoption/api-tokens)
-* [User consent and third-party applications](/api-auth/user-consent)
-* [Custom user profile claims and `scope`](/api-auth/tutorials/adoption/scope-custom-claims)
-* [Single sign-on (SSO)](/api-auth/tutorials/adoption/single-sign-on)
+* [Call APIs with Auth0 Tokens](/api-auth/tutorials/adoption/api-tokens)
+* [User Consent and Third-Party Applications](/api-auth/user-consent)
+* [User Profile Claims and the `scope` Parameter](/api-auth/tutorials/adoption/scope-custom-claims)
+* [Single Sign-on (SSO)](/api-auth/tutorials/adoption/single-sign-on)
* Initiating authentication flows:
- - [Authorization Code grant](/api-auth/tutorials/adoption/authorization-code)
- - [Implicit grant](/api-auth/tutorials/adoption/implicit)
- * [Silent authentication](/api-auth/tutorials/silent-authentication) (replaces Refresh Tokens for single-page applications)
- - [Resource Owner Password Credentials exchange](/api-auth/tutorials/adoption/password)
- - [Client Credentials exchange](/api-auth/tutorials/adoption/client-credentials) (only available in new pipeline)
+ - [Authorization Code Grant](/api-auth/tutorials/adoption/authorization-code)
+ - [Implicit Grant](/api-auth/tutorials/adoption/implicit)
+ * [Silent Authentication](/api-auth/tutorials/silent-authentication) (replaces Refresh Tokens for single-page applications)
+ - [Resource Owner Password Credentials Exchange](/api-auth/tutorials/adoption/password)
+ - [Client Credentials Exchange](/api-auth/tutorials/adoption/client-credentials) (only available in new pipeline)
* [Refresh Tokens](/api-auth/tutorials/adoption/refresh-tokens)
-* [Delegation (deprecated)](/api-auth/tutorials/adoption/delegation)
-* [Passwordless authentication](/api-auth/passwordless)
-* [List of breaking changes for OIDC-conformant applications](/api-auth/tutorials/adoption/oidc-conformant)
+* [Passwordless Authentication](/api-auth/passwordless)
+* [OIDC-Conformant Applications](/api-auth/tutorials/adoption/oidc-conformant)
diff --git a/articles/api-auth/tutorials/adoption/api-tokens.md b/articles/api-auth/tutorials/adoption/api-tokens.md
index 925393abcc..8c310789ec 100644
--- a/articles/api-auth/tutorials/adoption/api-tokens.md
+++ b/articles/api-auth/tutorials/adoption/api-tokens.md
@@ -1,24 +1,35 @@
---
-title: Calling your APIs with Auth0 tokens
+title: Call APIs with Auth0 Tokens
description: The OIDC-conformant pipeline and how this affects your use of Auth0 tokens with external APIs
+topics:
+ - tokens
+ - access-tokens
+ - id-tokens
+ - scopes
+ - api-authentication
+ - oidc
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Call your APIs with Auth0 tokens
+# Call APIs with Auth0 Tokens
<%= include('./_about.md') %>
-With the OIDC-conformant pipeline, [all APIs should be secured with Access Tokens, not ID tokens](/api-auth/why-use-access-tokens-to-secure-apis). In this article, we discuss what this means and what you need to do if you're using Auth0 tokens with your APIs.
+With the OIDC-conformant pipeline, all APIs should be secured with Access Tokens, not ID Tokens. In this article, we discuss what this means and what you need to do if you're using Auth0 tokens with your APIs.
## OIDC-conformant pipeline and tokens
In the OIDC-conformant pipeline, **ID Tokens should never be used as API tokens**.
-Instead, applications and APIs (resource services) should be defined as separate Auth0 entities. This allows you to obtain Access Tokens for your APIs.
+Instead, applications and APIs (resource services) should be defined as separate Auth0 entities. This allows you to obtain Access Tokens for your APIs.
-You get simpler API integration since your APIs are no longer tied to the applications that make calls to it. You're also enabling [machine-to-machine integration scenarios](/api-auth/grant/client-credentials), since applications
-can authenticate as themselves](/api-auth/grant/client-credentials (that is, they are not acting on behalf of any user) to programmatically and securely obtain an API token.
+You get simpler API integration since your APIs are no longer tied to the applications that make calls to it. You're also enabling [machine-to-machine integration scenarios](/flows/concepts/client-credentials), since applications
+can authenticate as themselves (that is, they are not acting on behalf of any user) to programmatically and securely obtain an API token.
For example, [the Auth0 Management API is already defined as a resource server on your
-Auth0 domain](${manage_url}/#/apis/management/settings). You can then authorize applications seeking access to obtain API tokens with specific scopes in a secure way.
+Auth0 domain](${manage_url}/#/apis/management/settings). You can then authorize applications seeking access to obtain API tokens with specific scopes in a secure way.
### Access vs. ID Tokens
@@ -45,7 +56,7 @@ One way to understand how Access and ID Tokens differ in their behavior is to lo
The sample above shows the contents of an ID Token. ID Tokens are meant only for **authenticating** the users to the **application**.
-Note that the audience value (located in the **aud** claim) of the token is set to the application's identifier. This means that only this specific application should consume the token.
+Note that the audience value (located in the **aud** claim) of the token is set to the application's identifier. This means that only this specific application should consume the token.
You can think of the ID Token as a performance optimization that allows applications to obtain user profile information without making additional requests after the completion of the authentication process. ID Tokens should never be used to obtain direct access to resources or to make authorization decisions.
@@ -72,7 +83,7 @@ The Access Token is meant to **authorize** the user to the **API (resource serve
The token does not contain any information about the user except for the user ID (located in the **sub** claim). The token only contains authorization information about the actions that application is allowed to perform at the API (such permissions are referred to as **scopes**).
-In many cases, you may find it useful to retrieve additional user information. You can do this by calling the [/userinfo API endpoint](/api/authentication#get-user-info) with the Access Token. Be sure that the API for which the Access Token is issued uses the **RS256** signing algorithm.
+In many cases, you may find it useful to retrieve additional user information. You can do this by calling the [/userinfo API endpoint](/api/authentication#get-user-info) with the Access Token. Be sure that the API for which the Access Token is issued uses the **RS256** [signing algorithm](/tokens/concepts/signing-algorithms).
## Scopes
@@ -81,13 +92,13 @@ With the OIDC-conformant pipeline, the **scope** parameter [behaves differently]
The scope parameter in the OIDC-conformant pipeline determines:
* The permissions that an authorized application should have for a given resource server
-* Which standard profile claims should be included in the ID token (if the user consents to provide this information to the application)
+* Which standard profile claims should be included in the ID Token (if the user consents to provide this information to the application)
If you have multiple apps calling an API under a single client ID, you should represent each application with a single Auth0 application, each of which can interact with the resource server representing the API on which these apps depend.
-Similarly, if you use [delegation to exchange tokens obtained by one application for tokens for a different application](/tokens/delegation), you should also be using a multi-application solution, each authenticating to the same resource server.
+Similarly, if you use delegation to exchange tokens obtained by one application for tokens for a different application, you should also be using a multi-application solution, each authenticating to the same resource server.
-If your applications do not depend on external APIs and you just need to authenticate users, you do not need to define a resource server/API as long as the ID tokens are:
+If your applications do not depend on external APIs and you just need to authenticate users, you do not need to define a resource server/API as long as the ID Tokens are:
* Processed only by the application
* Not sent to any external services
@@ -96,6 +107,6 @@ If your applications do not depend on external APIs and you just need to authent
For more information on API authentication and authorization refer to API Authorization.
:::
-## Further reading
+## Keep reading
-<%= include('./_index.md') %>
\ No newline at end of file
+<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/authorization-code.md b/articles/api-auth/tutorials/adoption/authorization-code.md
index dba7c59740..692a46e71f 100644
--- a/articles/api-auth/tutorials/adoption/authorization-code.md
+++ b/articles/api-auth/tutorials/adoption/authorization-code.md
@@ -1,12 +1,20 @@
---
description: OIDC-conformant Authorization Code grant
+topics:
+ - api-authentication
+ - oidc
+ - authorization-code
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Authorization Code grant
+# Authorization Code Grant
<%= include('./_about.md') %>
-The [Authorization Code grant](/api-auth/grant/authorization-code) is used by server-side applications that are capable of securely storing secrets, or by [native applications through PKCE](/api-auth/grant/authorization-code-pkce).
+The [Authorization Code Grant](/flows/concepts/auth-code) is used by server-side applications that are capable of securely storing secrets, or by [native applications through PKCE](/flows/concepts/auth-code-pkce).
This document describes the differences of this flow between the legacy and OIDC-conformant authentication pipelines.
## Authentication request
@@ -28,7 +36,7 @@ This document describes the differences of this flow between the legacy and OIDC
&redirect_uri=https://app.example.com/callback
&device=my-device-name
The returned Access Token is valid for optionally calling the API specified in the audience parameter and the /userinfo endpoint (provided that the API uses RS256 as the signing algorithm and openid is used as a scope parameter). If you are not implementing your own Resource Server (API), then you can use https://{$account.namespace}/userinfo as the audience parameter, which will return an opaque Access Token.
+
The returned Access Token is valid for optionally calling the API specified in the audience parameter and the /userinfo endpoint (provided that the API uses RS256 as the signing algorithm and openid is used as a scope parameter). If you are not implementing your own Resource Server (API), then you can use https://${account.namespace}/userinfo as the audience parameter, which will return an opaque Access Token.
A Refresh Token will be returned only if the offline_access scope was granted.
The returned Access Token is valid for optionally calling the API specified in the audience parameter and the /userinfo endpoint (provided that the API uses RS256 as the signing algorithm and openid is used as a scope parameter). If you are not implementing your own Resource Server (API), then you can use https://{$account.namespace}/userinfo as the audience parameter, which will return an opaque Access Token.
+
The returned Access Token is valid for optionally calling the API specified in the audience parameter and the /userinfo endpoint (provided that the API uses RS256 as the signing algorithm and openid is used as a scope parameter). If you are not implementing your own Resource Server (API), then you can use https://${account.namespace}/userinfo as the audience parameter, which will return an opaque Access Token.
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/client-credentials.md b/articles/api-auth/tutorials/adoption/client-credentials.md
index 2ef6dad266..bc6189bcf3 100644
--- a/articles/api-auth/tutorials/adoption/client-credentials.md
+++ b/articles/api-auth/tutorials/adoption/client-credentials.md
@@ -1,21 +1,29 @@
---
title: Client Credentials exchange
+topics:
+ - api-authentication
+ - oidc
+ - client-credentials
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Client Credentials exchange
+# Client Credentials Exchange
<%= include('./_about.md') %>
-The [Client Credentials exchange](/api-auth/grant/client-credentials) allows apps to authenticate as themselves (that is, not on behalf of any user) to programmatically and securely obtain access to an API.
+The [Client Credentials exchange](/flows/concepts/client-credentials) allows apps to authenticate as themselves (that is, not on behalf of any user) to programmatically and securely obtain access to an API.
This exchange does not exist in the legacy pipeline, but the [Resource Owner Password Credentials exchange](/api-auth/tutorials/adoption/password) can be used to simulate it by creating a "service user".
We strongly discourage the latter approach in favor of using Client Credentials, since it allows defining fine-grained permissions for each API app.
::: note
- For more information on how to execute a Client Credentials exchange refer to Call APIs from Client-side Web Apps.
+ For more information on how to execute a Client Credentials exchange, refer to Call API Using the Client Credentials Flow.
:::
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/delegation.md b/articles/api-auth/tutorials/adoption/delegation.md
index 0a243eeb85..8fea9b651a 100644
--- a/articles/api-auth/tutorials/adoption/delegation.md
+++ b/articles/api-auth/tutorials/adoption/delegation.md
@@ -1,15 +1,25 @@
---
title: Delegation and the OIDC-conformant pipeline
+topics:
+ - api-authentication
+ - oidc
+ - delegation
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Delegation and the OIDC-conformant pipeline
+# Delegation and the OIDC-Conformant Pipeline
+
+<%= include('../../../_includes/_deprecate-delegation') %>
<%= include('./_about.md') %>
[Delegation](/api/authentication#delegation) is used for many operations, depending on your particular use case:
* Exchanging an ID Token issued to one application for a new one issued to a different application
-* Using a Refresh Token to obtain a fresh ID Token
+* Using a Refresh Token to obtain a fresh ID Token
* Exchanging an ID Token for a third-party API token, such as Firebase or AWS.
Given that [ID Tokens should no longer be used as API tokens](/api-auth/tutorials/adoption/api-tokens) and that [Refresh Tokens should be used only at the token endpoint](/api-auth/tutorials/adoption/refresh-tokens), this endpoint is now considered deprecated.
@@ -22,6 +32,6 @@ At the moment there is no OIDC-compliant mechanism to obtain third-party API tok
In order to facilitate a gradual migration to the new authentication pipeline, delegation can still be used to obtain third-party API tokens.
This will be deprecated in future releases.
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/implicit.md b/articles/api-auth/tutorials/adoption/implicit.md
index 6758f17245..451729f8b3 100644
--- a/articles/api-auth/tutorials/adoption/implicit.md
+++ b/articles/api-auth/tutorials/adoption/implicit.md
@@ -1,12 +1,20 @@
---
-title: OIDC-conformant Implicit grant
+description: Understand how the implicit grant is used by apps that are incapable of securely storing secrets such as SPA JS apps.
+topics:
+ - api-authentication
+ - oidc
+ - implicit
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Implicit grant
+# Implicit Grant
<%= include('./_about.md') %>
-The [Implicit grant](/api-auth/grant/implicit) is used by applications that are incapable of securely storing secrets, such as single-page JavaScript applications.
+The [Implicit grant](/flows/concepts/implicit) is used by applications that are incapable of securely storing secrets, such as single-page JavaScript applications.
This document describes the differences of this flow between the legacy and OIDC-conformant authentication pipelines.
## Authentication request
@@ -28,7 +36,7 @@ This document describes the differences of this flow between the legacy and OIDC
&redirect_uri=https://app.example.com
&device=my-device-name
@@ -41,11 +49,11 @@ This document describes the differences of this flow between the legacy and OIDC
&redirect_uri=https://app.example.com
&audience=https://api.example.com
-
This response_type parameter indicates that we want to receive both an Access Token and ID Token.
The returned Access Token is valid for calling the /userinfo endpoint (provided that the API specified by the audience param uses RS256 as signing algorithm) and optionally the resource server specified by the audience parameter.
+
The returned Access Token is valid for calling the /userinfo endpoint (provided that the API specified by the audience param uses RS256 as signing algorithm) and optionally the resource server specified by the audience parameter.
If using response_type=id_token, Auth0 will only return an ID Token.
The returned Access Token is a JWT valid for calling the /userinfo endpoint(provided that the API specified by the audience param uses RS256 as signing algorithm) as well as the resource server specified by the audience parameter.
+
The returned Access Token is a JWT valid for calling the /userinfo endpoint(provided that the API specified by the audience param uses RS256 as signing algorithm) as well as the resource server specified by the audience parameter.
Note that an opaque Access Token could still be returned if /userinfo is the only specified audience.
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/index.md b/articles/api-auth/tutorials/adoption/index.md
index 8007cacb77..eb7827dc97 100644
--- a/articles/api-auth/tutorials/adoption/index.md
+++ b/articles/api-auth/tutorials/adoption/index.md
@@ -1,6 +1,13 @@
---
url: /api-auth/tutorials/adoption
title: OIDC Conformant Authentication Adoption Guide
+topics:
+ - api-authentication
+ - oidc
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
# OIDC Conformant Authentication Adoption Guide
@@ -15,7 +22,7 @@ This guide details all the upcoming changes, **some of which will be breaking**,
This guide is meant for developers and IT admins who manage Auth0 integrations in their applications. If you are not familiar with how OAuth works at a basic level, [we suggest reading our protocol overview](/protocols/oauth2).
-If you are integrating Auth0 as a [SAML or WS-Federation **identity provider**](/saml-idp-generic) to your application (that is, not through OIDC/OAuth), then you do not need to make any changes.
+If you are integrating Auth0 as a [SAML or WS-Federation **identity provider**](/saml-idp-generic) for your application (that is, not through OIDC/OAuth), then you do not need to make any changes.
To make this guide accessible to everyone, any authentication flows will be described only through HTTP requests instead of in the context of any particular language or library's implementation. This is the similar to the descriptions and examples provided by the [official OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html).
@@ -23,7 +30,7 @@ To make this guide accessible to everyone, any authentication flows will be desc
All of the changes described in this guide apply to the **OIDC Conformant Authentication Pipeline**. This pipeline will be used if **any** of the following are true:
-- An [authentication request](/api/authentication#social) was initiated with an `audience` parameter.
+- An [authentication request](/api/authentication#social) was initiated with an `audience` parameter.
- The application being used is flagged as **OIDC Conformant** (available at _Dashboard > Applications > Settings > Show advanced settings > OAuth > OIDC Conformant flag_).
@@ -45,6 +52,6 @@ We understand that making changes to the core authentication logic of your appli
All Auth0 documentation, SDKs, libraries and samples will eventually apply only to the OIDC-conformant pipeline. Because of this, we strongly recommend adoption even if you do not need to leverage any new features or functionality in the near future.
-## Compare differences between the two pipelines
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/oidc-conformant.md b/articles/api-auth/tutorials/adoption/oidc-conformant.md
index fac12b6fd0..a8a601f4ad 100644
--- a/articles/api-auth/tutorials/adoption/oidc-conformant.md
+++ b/articles/api-auth/tutorials/adoption/oidc-conformant.md
@@ -1,9 +1,15 @@
---
-title: OIDC-conformant applications
description: List of breaking changes for OIDC-conformant applications
+topics:
+ - api-authentication
+ - oidc
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# OIDC-conformant applications
+# OIDC-Conformant Applications
<%= include('./_about.md') %>
@@ -14,30 +20,31 @@ In order to make the transition to the [OIDC-conformant authentication pipeline]
The objective of this flag is to disable as many legacy features as possible, so you can run into the OIDC-conformant pipeline's breaking changes at configuration time rather than run time.
Enabling this flag on an application will have the following effects:
-* The following features are deprecated in favor of [silent authentication](/api-auth/tutorials/adoption/implicit):
- - Refresh Tokens on authentication with the [implicit grant](/api-auth/tutorials/adoption/implicit)
+* The following features are deprecated:
+ - Refresh Tokens on authentication with the [implicit grant](/api-auth/tutorials/adoption/implicit)
- /ssodata endpoint and `getSSOData()` method from Lock/auth0.js
-* [Single sign-on (SSO)](/api-auth/tutorials/adoption/single-sign-on) can only be performed from Auth0 login pages.
-* Using `response_type=token` will only return an Access Token, not an ID Token. Use `response_type=id_token` or `response_type=token id_token` instead.
+* [Single Sign-on (SSO)](/api-auth/tutorials/adoption/single-sign-on) can only be performed from Auth0 login pages.
+* Using `response_type=token` will only return an Access Token, not an ID Token. Use `response_type=id_token` or `response_type=token id_token` instead.
* ID Tokens obtained with the implicit grant will be signed asymmetrically using RS256.
* The /tokeninfo endpoint is disabled.
* Responses from /userinfo will [conform to the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse), similar to the [contents of ID Tokens](/api-auth/tutorials/adoption/scope-custom-claims)
-* Implicit grant authentication requests made without a [`nonce` parameter](/api-auth/tutorials/nonce) will be rejected.
+* Implicit grant authentication requests made without a [`nonce` parameter](/api-auth/tutorials/nonce) will be rejected.
* [Refresh Tokens must be used at the token endpoint]() instead of /delegation.
* The `device` parameter, originally used to obtain Refresh Tokens, is now considered invalid.
* The legacy [resource owner endpoint](/api/authentication#database-ad-ldap-active-) is disabled.
- - Passwordless authentication for embedded login is implemented at this endpoint, so it will be disabled as well.
+ - Passwordless authentication for embedded login is implemented at this endpoint, so it will be disabled as well.
* The [/oauth/access_token endpoint](/api/authentication#post-oauth-access_token), used for social authentication from native mobile applications, is disabled.
An OIDC-conformant alternative will be added in future releases.
* The [`scope` parameter of authentication requests](/api-auth/tutorials/adoption/scope-custom-claims) will comply to the OIDC specification:
- - Custom claims must be namespaced and added to ID Tokens or Access Tokens via rules.
- - Custom scope values can be defined by a [resource server (API)](/api-auth/tutorials/adoption/api-tokens).
+ - Custom claims must be [namespaced](/tokens/guides/create-namespaced-custom-claims) and added to ID Tokens or Access Tokens via rules.
+ - The namespace identifiers for custom claims must be **HTTP** or **HTTPS** URIs.
+ - Custom scope values can be defined by a [resource server (API)](/api-auth/tutorials/adoption/api-tokens).
* OIDC-conformant applications cannot be the source or target application of a [delegation request](/api-auth/tutorials/adoption/delegation).
## I don't want to make all these changes at once!
The "OIDC Conformant" flag will force all of these changes at the same time for a given application, but it's not the only option to gradually transition to the OIDC-conformant authentication pipeline.
-Any authentication requests made with an `audience` parameter will use the new pipeline, and all other requests will continue to work as usual.
+Any authentication requests made with an `audience` parameter will use the new pipeline, and all other requests will continue to work as usual.
If your application doesn't need a resource server but you want opt-in to the new pipeline on a per-request basis, you can use the following `audience` parameter:
@@ -45,6 +52,6 @@ If your application doesn't need a resource server but you want opt-in to the ne
https://${account.namespace}/userinfo
```
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/password.md b/articles/api-auth/tutorials/adoption/password.md
index 99221fe23b..15834e8bba 100644
--- a/articles/api-auth/tutorials/adoption/password.md
+++ b/articles/api-auth/tutorials/adoption/password.md
@@ -1,7 +1,17 @@
---
-title: OIDC-conformant Resource Owner Password Credentials exchange
+description: Understand how the Resource Owner Password Grant (ROPG) is used by highly-trusted apps to provide active authentication.
+topics:
+ - api-authentication
+ - oidc
+ - resource-owner-password
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Resource Owner Password Credentials exchange
+# Resource Owner Password Credentials Exchange
+
+<%= include('../../_includes/_ropg-warning.md') %>
<%= include('./_about.md') %>
@@ -32,21 +42,15 @@ Content-Type: application/json
"device": "my-device-name"
}
The endpoint to execute token exchanges is /oauth/token.
Auth0's own grant type is used to authenticate users from a specific connection (realm). The standard OIDC password grant is also supported, but it does not accept Auth0-specific parameters such as realm.
The returned Access Token is valid for calling the /userinfo endpoint (provided that the API specified by the audience param uses RS256 as signing algorithm) and optionally the resource server specified by the audience parameter.
-
The ID Token will be forcibly signed using RS256 if requested by a public application.
+
The returned Access Token is valid for calling the /userinfo endpoint (provided that the API specified by the audience param uses RS256 as signing algorithm) and optionally the resource server specified by the audience parameter.
+
The ID Token will be forcibly signed using RS256 if requested by a public application.
A Refresh Token will be returned only if the offline_access scope was granted.
@@ -142,7 +146,7 @@ Pragma: no-cache
}
The ID Token will be forcibly signed using RS256 if requested by a public application.
-
The favorite_color claim must be namespaced and added through a rule.
+
The favorite_color claim must be namespaced and added through a rule.
The returned Access Token is a JWT valid for calling the /userinfo endpoint (provided that the API specified by the audience param uses RS256 as signing algorithm) as well as the resource server specified by the audience parameter.
+
The returned Access Token is a JWT valid for calling the /userinfo endpoint (provided that the API specified by the audience param uses RS256 as signing algorithm) as well as the resource server specified by the audience parameter.
Note that an opaque Access Token could still be returned if /userinfo is the only specified audience.
@@ -189,6 +193,6 @@ Pragma: no-cache
The Auth0 password realm grant is not defined by standard OIDC, but it is suggested as an alternative to the legacy resource owner endpoint because it supports the Auth0-specific `realm` parameter. The [standard OIDC grant is also supported](/api-auth/tutorials/password-grant) when using OIDC authentication.
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/refresh-tokens.md b/articles/api-auth/tutorials/adoption/refresh-tokens.md
index fe50b40c64..fa8d7447b6 100644
--- a/articles/api-auth/tutorials/adoption/refresh-tokens.md
+++ b/articles/api-auth/tutorials/adoption/refresh-tokens.md
@@ -1,27 +1,35 @@
---
-title: OIDC-conformant Refresh Token use
+description: Understand how refresh tokens are used in an OIDC-conformant authentication pipeline.
+topics:
+ - api-authentication
+ - oidc
+ - tokens
+ - refresh tokens
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# OIDC-conformant Refresh Tokens
+# OIDC-Conformant Refresh Tokens
<%= include('./_about.md') %>
-There are some changes to how Refresh Tokens are used in the OIDC-conformant authentication pipeline:
+There are some changes to how Refresh Tokens are used in the OIDC-conformant authentication pipeline:
* Using the [implicit grant](/api-auth/tutorials/adoption/implicit) for authentication will no longer return Refresh Tokens.
- Use [silent authentication](/api-auth/tutorials/silent-authentication) (such as `prompt=none`) instead.
-* Refresh Tokens should only be used by [confidential applications](/applications/application-types#confidential-applications). However, they can also be used by Native (public) applications to obtain Refresh Tokens for mobile apps.
-* The `/delegation` endpoint is considered deprecated. To obtain new tokens from a Refresh Token, the `/oauth/token` endpoint should be used instead:
+* Refresh Tokens should only be used by [confidential applications](/applications/concepts/app-types-confidential-public#confidential-applications). However, they can also be used by Native (public) applications to obtain Refresh Tokens for mobile apps.
+* The `/delegation` endpoint is deprecated. To obtain new tokens from a Refresh Token, the `/oauth/token` endpoint should be used instead:
The audience and client_secret parameters are optional. The client_secret is not needed when requesting a refresh_token for a mobile app.
@@ -51,6 +53,6 @@ Content-Type: application/json
Please note that Refresh Tokens must be kept confidential in transit and storage, and they should be shared only among the authorization server and the client to whom the Refresh Tokens were issued.
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/scope-custom-claims.md b/articles/api-auth/tutorials/adoption/scope-custom-claims.md
index 43cc9e60ac..10b72653ed 100644
--- a/articles/api-auth/tutorials/adoption/scope-custom-claims.md
+++ b/articles/api-auth/tutorials/adoption/scope-custom-claims.md
@@ -1,14 +1,24 @@
---
-title: User profile claims and scope
+description: Apps can request any standard OIDC scopes such as profile and email as well as any scopes supported by the API they want to access.
+topics:
+ - api-authentication
+ - oidc
+ - scopes
+ - user-profiles
+ - claims
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# User profile claims and scope
+# User Profile Claims and the `scope` Parameter
<%= include('./_about.md') %>
-The behavior of the `scope` parameter has been changed to conform to the [OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims).
+The behavior of the `scope` parameter has been changed to conform to the [OpenID Connect (OIDC) specification](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims).
-Instead of requesting arbitrary application-specific claims, applications can request any of the standard OIDC scopes such as `profile` and `email`, as well as any [scopes supported by the API they want to access](/api-auth/tutorials/adoption/api-tokens).
+Instead of requesting arbitrary application-specific claims, applications can request any of the standard OIDC scopes such as `profile` and `email`, as well as any [scopes supported by the API they want to access](/api-auth/tutorials/adoption/api-tokens).
## Standard claims
@@ -16,7 +26,7 @@ The OIDC specification defines a [set of standard claims](https://openid.net/spe
## Custom claims
-To improve compatibility for applications, Auth0 now returns profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). You can still add custom claims, but they must conform to a namespaced format to avoid possible collisions with standard OIDC claims. Otherwise, it is no longer possible to add arbitrary claims to ID Tokens or Access Tokens.
+To improve compatibility for applications, Auth0 now returns profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). You can still add custom claims, but they must conform to a namespaced format to avoid possible collisions with standard OIDC claims. Otherwise, it is no longer possible to add arbitrary claims to ID Tokens or Access Tokens.
For example, suppose an identity provider returns a `favorite_color` claim as part of the user’s profile, and that we’ve used the Auth0 management API to set application-specific information for this user.
@@ -34,7 +44,7 @@ This would be the profile stored by Auth0:
}
```
-This is a [*normalized user profile*](/user-profile/normalized), which is a protocol-agnostic representation of this user as defined by Auth0. When performing an OIDC conformant login, Auth0 would return the following ID Token claims to the application:
+This is a [*normalized user profile*](/users/normalized), which is a protocol-agnostic representation of this user as defined by Auth0. When performing an OIDC conformant login, Auth0 would return the following ID Token claims to the application:
```json
{
@@ -48,7 +58,7 @@ This is a [*normalized user profile*](/user-profile/normalized), which is a prot
}
```
-Note that the `user_id` property is sent as `sub` in the ID Token, and that `favorite_color` and `user_metadata` are not present in the OIDC response from Auth0. This is because OIDC does not define standard claims to represent all the information in this user’s profile. We can, however, define a non-standard claim by namespacing it through a rule:
+Note that the `user_id` property is sent as `sub` in the ID Token, and that `favorite_color` and `user_metadata` are not present in the OIDC response from Auth0. This is because OIDC does not define standard claims to represent all the information in this user’s profile. We can, however, define a non-standard claim by namespacing it through a [rule](/rules):
```js
function (user, context, callback) {
@@ -59,18 +69,33 @@ function (user, context, callback) {
}
```
+::: note
+If you need to add custom claims to the Access Token, you can use the code sample above with the following change: use `context.accessToken` in place of `context.idToken`.
+
+Please note that adding custom claims to tokens through this method will also let you obtain them when calling the `/userinfo` endpoint. However, rules run when the user is authenticating, not when `/userinfo` is called.
+:::
+
Any non-Auth0 HTTP or HTTPS URL can be used as a namespace identifier, and any number of namespaces can be used. The namespace URL does not have to point to an actual resource, it’s only used as an identifier and will not be called by Auth0.
::: warning
`auth0.com`, `webtask.io` and `webtask.run` are Auth0 domains and therefore cannot be used as a namespace identifier.
:::
-This follows a [recommendation from the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#AdditionalClaims) stating that custom claim identifiers should be collision-resistant. While this is not mandatory according to the specification, Auth0 will always enforce namespacing when performing OIDC-conformant login flows, meaning that any non-namespaced claims will be silently excluded from tokens.
+This follows a [recommendation from the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#AdditionalClaims) stating that custom claim identifiers should be collision-resistant. While this is not mandatory according to the specification, Auth0 will always enforce namespacing when performing OIDC-conformant login flows, meaning that any custom claims without HTTP/HTTPS namespaces will be silently excluded from tokens.
+
+::: note
+Auth0 will allow non-OIDC claims without a namespace (the "legacy" user profile, from which we strongly recommend moving away) if:
+
+* You are using the non-OIDC conformant pipeline (i.e., you are not using the `audience` parameter in the `/authorize` or token request and the application does not have the [**OIDC-Conformant** toggle](https://auth0.com/docs/api-auth/tutorials/adoption/oidc-conformant) enabled).
+* You have the **Legacy User Profile** toggle turned on in the [tenant Advanced Settings](https://manage.auth0.com/#/tenant/advanced), under the **Migrations** section. This setting is only enabled for old tenants, but newly created tenants can't see or enable the **Legacy User Profile**.
+
+We strongly recommend moving away from the Legacy User Profile.
+:::
-If you need to add custom claims to the Access Token, the same applies but using `context.accessToken` instead.
+## Token refresh flow and custom claims
-Please note that adding custom claims to ID Tokens through this method will also let you obtain them when calling the `/userinfo` endpoint. However, rules run when the user is authenticating, not when `/userinfo` is called.
+When an application requests new tokens using a Refresh Token, the new tokens will not automatically inherit any custom claims previously added. But since rules run on a token refresh flow as well, the same claim customization code will be executed in these cases. This gives the flexibility of adding or changing claims in newly issued tokens without forcing applications to obtain a new refresh token.
-## Further reading
+## Keep reading
<%= include('./_index.md') %>
diff --git a/articles/api-auth/tutorials/adoption/single-sign-on.md b/articles/api-auth/tutorials/adoption/single-sign-on.md
index 5955fd4412..f421306e27 100644
--- a/articles/api-auth/tutorials/adoption/single-sign-on.md
+++ b/articles/api-auth/tutorials/adoption/single-sign-on.md
@@ -1,24 +1,30 @@
---
-title: OIDC Single sign-on
+description: Understand how OIDC Single Sign-On occurs when a user logs into one app and is then signed into other apps automatically.
+topics:
+ - api-authentication
+ - oidc
+ - sso
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
---
-# Single sign-on
+# OIDC Single Sign-On
<%= include('./_about.md') %>
-Single sign-on (SSO) occurs when a user logs in to one application and is then signed in to other applications automatically.
+Single Sign-on (SSO) occurs when a user logs into one application and is then signed into other applications automatically.
In the context of the OIDC-conformant authentication pipeline, SSO must happen at the authorization server (i.e. Auth0) and not applications.
-This means that for SSO to happen, you must employ [universal login](/hosted-pages/login) and redirect users to the login page.
+This means that for SSO to happen, you must employ Universal Login and redirect users to the login page.
-We are planning on providing support for SSO from applications in future releases.
-
-## How SSO works
+## How it works
At a general level, this is what happens when performing SSO:
-1. If the user is not logged in locally, redirect them to Auth0 for authentication. This is done using the [authorization code](/api-auth/grant/authorization-code) or [implicit](/api-auth/grant/implicit) grants, depending on the type of application.
+1. If the user is not logged in locally, redirect them to Auth0 for authentication. This is done using the [Authorization Code Flow](/flows/concepts/auth-code) or [Implicit Flow](/flows/concepts/implicit), depending on the type of application.
2. If the user was logged in through SSO, Auth0 will immediately authenticate them without needing to re-enter credentials.
An application that does not use SSO might decide to use embedded login to authenticate users instead of redirecting to Auth0 for authentication.
@@ -32,13 +38,13 @@ OIDC-conformant applications must use [silent authentication](/api-auth/tutorial
## Authentication flows without SSO
-SSO sessions are managed by Auth0 setting a cookie on your Auth0 domain.
+SSO [sessions](/sessions) are managed by Auth0 setting a cookie on your Auth0 domain.
Since cross-origin requests cannot set cookies, this means that SSO sessions must be established by redirecting users to your Auth0 login page (`/authorize`).
The following flows are redirect-based and are capable of SSO:
-* [Authorization code grant](/api-auth/grant/authorization-code)
-* [Implicit grant](/api-auth/grant/implicit)
+* [Authorization Code Flow](/flows/concepts/auth-code)
+* [Implicit Flow](/flows/concepts/implicit)
The following flows are request-based and are currently not capable of SSO:
@@ -46,8 +52,11 @@ The following flows are request-based and are currently not capable of SSO:
## Custom domains
-When using universal login, the login page is by default hosted at an Auth0 domain, so any SSO will be performed at an Auth0 domain instead of your organization's domain.
+When using Universal Login, the login page is by default hosted at an Auth0 domain, so any SSO will be performed at an Auth0 domain instead of your organization's domain.
This is only an aesthetic limitation and does not impact the security or functionality of SSO logins in any way.
-You can read further about [customizing your domain](/custom-domains) if you require it, to help maintain a uniform experience for your users.
+## Keep reading
+
+* [Custom Domains](/custom-domains)
+* [OIDC Handbook](https://auth0.com/resources/ebooks/the-openid-connect-handbook)
diff --git a/articles/api-auth/tutorials/authorization-code-grant-pkce.md b/articles/api-auth/tutorials/authorization-code-grant-pkce.md
index 019e24b629..e93cd3913b 100644
--- a/articles/api-auth/tutorials/authorization-code-grant-pkce.md
+++ b/articles/api-auth/tutorials/authorization-code-grant-pkce.md
@@ -1,20 +1,27 @@
---
description: How to execute an Authorization Code Grant flow with PKCE for a Mobile Application
toc: true
+topics:
+ - api-authentication
+ - oidc
+ - authorization-code
+ - pkce
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
---
# Execute an Authorization Code Grant Flow with PKCE
-<%= include('../../_includes/_pipeline2') %>
-
::: note
-This tutorial will help you implement the Authorization Code (PKCE) grant. If you are looking for some theory on the flow refer to [Calling APIs from Mobile App](/api-auth/grant/authorization-code-pkce).
+This tutorial will help you implement the Authorization Code (PKCE) grant. If you are looking for some theory on the flow refer to [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce).
:::
The __Authorization Code with PKCE__ is the OAuth 2.0 grant that [native apps](/quickstart/native) use in order to access an API. In this document we will work through the steps needed in order to implement this: create a code verifier and a code challenge, get the user's authorization, get a token and access the API using the token.
Before beginning this tutorial, please:
-* Check that your Application's [Grant Type property](/Applications/Application-grant-types) is set appropriately
+* Check that your Application's [Grant Type property](/applications/concepts/application-grant-types) is set appropriately
* [Register the API](/apis#how-to-configure-an-api-in-auth0) with Auth0
## 1. Create a Code Verifier
@@ -153,7 +160,7 @@ Where:
* `audience`: The unique identifier of the API the native app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial.
-* `scope`: The [scopes](/scopes) that you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must conform to a namespaced format, or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [API Settings](${manage_url}/#/apis)). The custom scopes must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims). For more information on this, refer to the [Namespacing Custom Claims](#optional-customize-the-tokens) panel.
+* `scope`: The scopes that you want to request authorization for. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [API Settings](${manage_url}/#/apis)).
* `response_type`: Denotes the kind of credential that Auth0 will return (code vs token). For this flow, the value must be `code`.
@@ -179,18 +186,39 @@ For example:
## 4. Exchange the Authorization Code for an Access Token
-Now that you have an Authorization Code, you must exchange it for an Access Token that can be used to call your API. Using the Authorization Code (`code`) from the previous step, you will need to `POST` to the [Token URL](/api/authentication#authorization-code-pkce-) sending also the `code_verifier`:
+Now that you have an Authorization Code, you must exchange it for an Access Token that can be used to call your API. Using the Authorization Code (`code`) from the previous step, you will need to `POST` to the [Token URL](/api/authentication#authorization-code-pkce-) sending also the `code_verifier`:
```har
{
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"com.myclientapp://myclientapp.com/callback\", }"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "code_verifier",
+ "value": "YOUR_GENERATED_CODE_VERIFIER"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "${account.callback}"
+ }
+ ]
}
}
```
@@ -214,15 +242,15 @@ The response contains `access_token`, `refresh_token`, `id_token`, and `token_ty
}
```
-Note that `refresh_token` will only be present in the response if you included the `offline_access` scope AND enabled __Allow Offline Access__ for your API in the Dashboard. For more information about Refresh Tokens and how to use them, see [our documentation](/tokens/refresh-token).
+Note that `refresh_token` will only be present in the response if you included the `offline_access` scope AND enabled __Allow Offline Access__ for your API in the Dashboard. See [Refresh Tokens](/tokens/concepts/refresh-tokens) for more information.
::: warning
-The Authorization Code flow with PKCE can only be used for Applications whose type is `Native` in the Dashboard.
+The Authorization Code flow with PKCE can only be used for Applications whose type is `Native` or `Single Page Application` in the Dashboard.
:::
## 5. Call the API
-Once you have the `access_token`, you can use it to make calls to the API, by passing it as a Bearer Token in the `Authorization` header of the HTTP request:
+Once you have the Access Token, you can use it to make calls to the API, by passing it as a Bearer Token in the `Authorization` header of the HTTP request:
```har
{
@@ -237,9 +265,9 @@ Once you have the `access_token`, you can use it to make calls to the API, by pa
## 6. Verify the Token
-Once your API receives a request with a Bearer `access_token`, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
+Once your API receives a request with a Bearer Access Token, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
-For details on the validations that should be performed refer to [Verify Access Tokens](/api-auth/tutorials/verify-access-token).
+For details on the validations that should be performed, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
## Optional: Customize the Tokens
@@ -249,16 +277,13 @@ If you wish to execute special logic unique to the Authorization Code (PKCE) gra
## Sample application
-For an example implementation see the [Mobile + API](/architecture-scenarios/application/mobile-api) architecture scenario.
+For an example implementation see the [Mobile + API](/architecture-scenarios/application/mobile-api) architecture scenario.
This is a series of tutorials that describe a scenario for a fictitious company. The company wants to implement a mobile app that the employees can use to send their timesheets to the company's Timesheets API using OAuth 2.0. The tutorials are accompanied by a sample that you can access in [GitHub](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets).
## Keep reading
-::: next-steps
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
+- [Tokens](/tokens)
- [Application Authentication for Mobile & Desktop Apps](/Application-auth/mobile-desktop)
- [The OAuth 2.0 protocol](/protocols/oauth2)
- [The OpenID Connect protocol](/protocols/oidc)
-- [Tokens used by Auth0](/tokens)
-:::
diff --git a/articles/api-auth/tutorials/authorization-code-grant.md b/articles/api-auth/tutorials/authorization-code-grant.md
index 5717deb3c1..5ecd2127c1 100644
--- a/articles/api-auth/tutorials/authorization-code-grant.md
+++ b/articles/api-auth/tutorials/authorization-code-grant.md
@@ -1,11 +1,17 @@
---
description: How to execute an Authorization Code Grant flow from a Regular Web application
toc: true
+topics:
+ - api-authentication
+ - oidc
+ - authorization-code
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
---
# Execute an Authorization Code Grant Flow
-<%= include('../../_includes/_pipeline2') %>
-
::: note
This tutorial will help you implement the Authorization Code grant. If you are looking for some theory on the flow refer to [Calling APIs from Server-side Web Apps](/api-auth/grant/authorization-code).
:::
@@ -14,7 +20,7 @@ The __Authorization Code__ is an OAuth 2.0 grant that [regular web apps](/quicks
Before beginning this tutorial, please:
-* Check that your Application's [Grant Type property](/applications/application-grant-types) is set appropriately
+* Check that your Application's [Grant Type property](/applications/concepts/application-grant-types) is set appropriately
* [Register the API](/apis#how-to-configure-an-api-in-auth0) with Auth0
## 1. Get the User's Authorization
@@ -35,13 +41,13 @@ Where:
* `audience`: The unique identifier of the API the web app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial.
-* `scope`: The [scopes](/scopes) which you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must conform to a namespaced format, or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [API Settings](${manage_url}/#/apis)). The custom scopes must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims). For more information on this, refer to the [Namespacing Custom Claims](#optional-customize-the-tokens) panel.
+* `scope`: The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [API Settings](${manage_url}/#/apis)).
* `response_type`: Denotes the kind of credential that Auth0 will return (code vs token). For this flow, the value must be `code`.
* `client_id`: Your application's Client ID. You can find this value at your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-* `state`: An opaque value the application adds to the initial request that Auth0 includes when redirecting back to the application. This value must be used by the application to prevent CSRF attacks, [click here to learn more](/protocols/oauth-state).
+* `state`: An opaque value the application adds to the initial request that Auth0 includes when redirecting back to the application. This value must be used by the application to prevent CSRF attacks. For more information, see [State Parameter](/protocols/oauth-state).
* `redirect_uri`: The URL to which Auth0 will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the `code` URL parameter. This URL must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
@@ -59,18 +65,39 @@ Note that if you alter the value in `scope`, Auth0 will require consent to be gi
## 2. Exchange the Authorization Code for an Access Token
-Now that you have an Authorization Code, you must exchange it for an Access Token that can be used to call your API. Using the Authorization Code (`code`) from the previous step, you will need to `POST` to the [Token URL](/api/authentication?http#authorization-code):
+Now that you have an Authorization Code, you must exchange it for an Access Token that can be used to call your API. Using the Authorization Code (`code`) from the previous step, you will need to `POST` to the [Token URL](/api/authentication?http#authorization-code):
```har
{
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"${account.callback}\"}"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "${account.callback}"
+ }
+ ]
}
}
```
@@ -94,15 +121,15 @@ The response contains the `access_token`, `refresh_token`, `id_token`, and `toke
}
```
-Note that `refresh_token` will only be present in the response if you included the `offline_access` scope AND enabled __Allow Offline Access__ for your API in the Dashboard. For more information about Refresh Tokens and how to use them, see [our documentation](/tokens/refresh-token).
+Note that `refresh_token` will only be present in the response if you included the `offline_access` scope AND enabled __Allow Offline Access__ for your API in the Dashboard. See [Refresh Tokens](/tokens/concepts/refresh-tokens) for more information.
::: panel-warning Security Warning
-It is important to understand that the Authorization Code flow should only be used in cases such as a Regular Web Application where the Client Secret can be safely stored. In cases such as a Single Page Application, the Client Secret is available to the application (in the web browser), so the integrity of the Client Secret cannot be maintained. That is why the [Implicit Grant flow](/api-auth/grant/implicit) is more appropriate in that case.
+It is important to understand that the Authorization Code flow should only be used in cases such as a Regular Web Application where the Client Secret can be safely stored. In cases such as a Single-Page Application, the Client Secret is available to the application (in the web browser), so the integrity of the Client Secret cannot be maintained. That is why the [Authorization Code Flow with PKCE ](/flows/concepts/auth-code-pkce) is more appropriate in that case.
:::
## 3. Call the API
-Once the `access_token` has been obtained it can be used to make calls to the API by passing it as a Bearer Token in the `Authorization` header of the HTTP request:
+Once the Access Token has been obtained it can be used to make calls to the API by passing it as a Bearer Token in the `Authorization` header of the HTTP request:
```har
{
@@ -117,9 +144,9 @@ Once the `access_token` has been obtained it can be used to make calls to the AP
## 4. Verify the Token
-Once your API receives a request with a Bearer `access_token`, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
+Once your API receives a request with a Bearer Access Token, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
-For details on the validations that should be performed refer to [Verify Access Tokens](/api-auth/tutorials/verify-access-token).
+For details on the validations that should be performed, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
## Optional: Customize the Tokens
@@ -129,10 +156,7 @@ If you wish to execute special logic unique to the Authorization Code grant, you
## Keep Reading
-::: next-steps
-- [How to refresh a token](/tokens/refresh-token)
+- [Refresh Tokens](/tokens/concepts/refresh-token)
- [How to configure an API in Auth0](/apis)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
- [Application Authentication for Server-side Web Apps](/application-auth/server-side-web)
-- [Tokens used by Auth0](/tokens)
-:::
+- [Tokens](/tokens)
diff --git a/articles/api-auth/tutorials/client-credentials.md b/articles/api-auth/tutorials/client-credentials.md
index 75827d2fbc..567e903447 100644
--- a/articles/api-auth/tutorials/client-credentials.md
+++ b/articles/api-auth/tutorials/client-credentials.md
@@ -1,16 +1,26 @@
---
-title: How to implement the Client Credentials Grant
-description: How to call an API from a server process using OAuth 2.0 and the Client Credentials grant
+description: Learn how to call an API from a server process using OAuth 2.0 and the Client Credentials grant.
toc: true
+topics:
+ - api-authentication
+ - oidc
+ - client-credentials
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
---
-# How to Implement the Client Credentials Grant
+# Implement the Client Credentials Grant
-<%= include('../../_includes/_pipeline2') %>
+The **Client Credentials Grant** (defined in [RFC 6749, section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)) allows an application to request an Access Token using its __Client Id__ and __Client Secret__. It is used for non interactive applications (a CLI, a daemon, or a Service running on your backend) where the token is issued to the application itself, instead of an end user.
Before beginning this tutorial, please:
-* Check that your Application's [Grant Type property](/applications/application-grant-types) is set appropriately
-* [Register the API](/apis#how-to-configure-an-api-in-auth0) with Auth0
+* Make sure you that your application has the `Client Credentials` [grant type enabled](/dashboard/guides/applications/update-grant-types). Regular web applications and machine to machine applications have it enabled by default.
+
+* [Register the API](/apis#how-to-configure-an-api-in-auth0) with Auth0 with the required scopes.
+
+* Authorize the application to call the API by creating a Client Grant either [using the Dashboard](/api-auth/config/using-the-auth0-dashboard) or [using the Management API](/api-auth/config/using-the-management-api).
## Ask for a token
@@ -21,11 +31,28 @@ To ask Auth0 for tokens for any of your authorized applications, perform a `POST
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"client_credentials\",\"client_id\": \"${account.clientId}\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"audience\": \"YOUR_API_IDENTIFIER\"}"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "client_credentials"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "audience",
+ "value": "YOUR_API_IDENTIFIER"
+ }
+ ]
}
}
```
@@ -33,11 +60,11 @@ To ask Auth0 for tokens for any of your authorized applications, perform a `POST
Where:
* `grant_type`: This must be `client_credentials`.
-* `client_id`: Your application's Client ID. You can find this value at the [Settings tab of the Machine to Machine Application](${manage_url}/#/applications).
-* `client_secret`: Your application's Client Secret. You can find this value at the [Settings tab of the Machine to Machine Application](${manage_url}/#/applications).
+* `client_id`: Your application's Client ID. You can find this value at the [application's settings tab](${manage_url}/#/applications).
+* `client_secret`: Your application's Client Secret. You can find this value at the [application's settings tab](${manage_url}/#/applications).
* `audience`: The **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial.
-The response contains a [signed JSON Web Token](/jwt), the token's type (which is `Bearer`), and in how much time it expires in [Unix time](https://en.wikipedia.org/wiki/Unix_time) (86400 seconds, which means 24 hours).
+The response contains a signed JSON Web Token (JWT), the token's type (which is `Bearer`), and in how much time it expires in [Unix time](https://en.wikipedia.org/wiki/Unix_time) (86400 seconds, which means 24 hours).
```json
{
@@ -52,7 +79,7 @@ If you [decode the `access_token`](https://jwt.io/#debugger-io) you will see tha
```json
{
"iss": "https://${account.namespace}/",
- "sub": "YOUR_NON_INTERACTIVE_CLIENT_ID@clients",
+ "sub": "YOUR_MACHINE_TO_MACHINE_APPLICATION_CLIENT_ID@clients",
"aud": "YOUR_API_IDENTIFIER",
"exp": 1489715431, // unix timestamp of the token's expiration date,
"iat": 1489679431, // unix timestamp of the token's creation date,
@@ -62,30 +89,25 @@ If you [decode the `access_token`](https://jwt.io/#debugger-io) you will see tha
## Modify scopes and claims
-You can change the scopes and add custom claims to the `access_token` you got, using [Hooks](/hooks).
+You can change the scopes and add custom claims to the Access Token you got, using [Hooks](/hooks).
-Hooks allow you to customize the behavior of Auth0 using Node.js code. They are actually Webtasks, associated with specific extensibility points of the Auth0 platform (like the Client Credentials grant). Auth0 invokes the Hooks at runtime to execute your custom logic.
+Hooks allow you to customize the behavior of Auth0 using Node.js code. They are secure, self-contained functions associated with specific extensibility points of the Auth0 platform (like the Client Credentials grant). Auth0 invokes the Hooks at runtime to execute your custom logic.
For more information and details on how to do that refer to [Using Hooks with Client Credentials Grant](/api-auth/tutorials/client-credentials/customize-with-hooks).
-
## Verify the token
-Once your API receives a request with a Bearer `access_token`, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
+Once your API receives a request with a Bearer Access Token, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
-For details on the validations that should be performed by the API, refer to [Verify Access Tokens](/api-auth/tutorials/verify-access-token).
+For details on the validations that should be performed by the API, see [Validate Access Tokens](/tokens/guides/validate-access-tokens). You can find examples on how to do it in different platforms in the [Quickstarts for backend applications](/quickstart/backend).
## Sample application
-For an example implementation see the [Server Client + API](/architecture-scenarios/application/server-api) architecture scenario.
+For an example implementation see the [Server Client + API](/architecture-scenarios/application/server-api) architecture scenario.
This is a series of tutorials that describe a scenario for a fictitious company that wants to implement a Timesheets API and send timesheets entries from a server process using OAuth 2.0. The tutorials are accompanied by a sample that you can access in [GitHub](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets).
## Keep reading
-::: next-steps
-- [Calling APIs from a Service](/api-auth/grant/client-credentials)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
-- [How to change the scopes and add custom claims to the tokens using Hooks](/api-auth/tutorials/client-credentials/customize-with-hooks)
-- [Tokens used by Auth0](/tokens)
-:::
+- [Use Hooks with Client Credentials Grant](/api-auth/tutorials/client-credentials/customize-with-hooks)
+- [Tokens](/tokens)
diff --git a/articles/api-auth/tutorials/client-credentials/customize-with-hooks.md b/articles/api-auth/tutorials/client-credentials/customize-with-hooks.md
index 925a2160c7..e8c5f642f2 100644
--- a/articles/api-auth/tutorials/client-credentials/customize-with-hooks.md
+++ b/articles/api-auth/tutorials/client-credentials/customize-with-hooks.md
@@ -2,34 +2,38 @@
description: How to use Hooks to change the scopes and add custom claims to the tokens you got using Client Credentials Grant.
crews: crew-2
toc: true
+topics:
+ - api-authentication
+ - oidc
+ - client-credentials
+ - hooks
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
+ - extensibility-hooks
---
-# Using Hooks with Client Credentials Grant
+# Use Hooks with Client Credentials Grant
-<%= include('../../../_includes/_pipeline2') %>
+You can now add [Hooks](/hooks) into your [client credentials](/api-auth/grant/client-credentials) flow. This way you can change the scopes and add custom claims to the tokens issued by Auth0.
-You can now add [Hooks](/hooks) into your [client credentials](/api-auth/grant/client-credentials) flow. This way you can change the scopes and add custom claims to the tokens issued by Auth0.
+Hooks allow you to customize the behavior of Auth0 using Node.js code. They are secure, self-contained functions associated with specific extensibility points of the Auth0 platform (like the Client Credentials grant). Auth0 invokes the Hooks at runtime to execute your custom logic.
-## Overview
-
-Hooks allow you to customize the behavior of Auth0 using Node.js code.
-
-They are actually [Webtasks](https://webtask.io/), associated with specific extensibility points of the Auth0 platform (like the Client Credentials grant). Auth0 invokes the Hooks at runtime to execute your custom logic.
-
-You can manage Hooks using the [Auth0 Dashboard](/hooks/dashboard) or the [Auth0 Command Line Interface (CLI)](/hooks/cli). In this article we will see how you can do either.
+You can manage Hooks using the Auth0 Dashboard or the Management API.
## Before you start
-Please ensure that:
+Create the following:
-- You have created an [API defined with the appropriate scopes](${manage_url}/#/apis)
-- You have created a [machine to machine application](${manage_url}/#/applications) that is authorized to use the API created in the previous step
+- [API defined with the appropriate scopes](${manage_url}/#/apis)
+- [Machine-to-machine application](/applications) authorized to use the API
-If you haven't done these yet, refer to these docs for details:
-- How to set up a Client Credentials Grant:
+For details on how to set up the API and the machine-to-machine app, see:
+- Set up a Client Grant:
- [Using the Dashboard](/api-auth/config/using-the-auth0-dashboard)
- [Using the Management API](/api-auth/config/using-the-management-api)
-- [How to execute a Client Credentials Grant](/api-auth/config/asking-for-access-tokens)
+- [Execute a Client Credentials Grant](/api-auth/config/asking-for-access-tokens)
## Use the Dashboard
@@ -47,11 +51,11 @@ If you haven't done these yet, refer to these docs for details:
You can create more than one hooks per extensibility point but __only one__ can be enabled. The enabled hook will then be executed for __all__ applications and APIs.
:::
-3. Click the __Pencil and Paper__ icon to the right of the Hook to open the Webtask Editor.
+3. Click the __Pencil and Paper__ icon to the right of the Hook to open the Hook Editor.

-4. Using the Webtask Editor, write your Node.js code. As an example, we will add an extra scope. The claim's name will be `https://foo.com/claim` and its value `bar`. Copy the sample code below and paste it in the Editor.
+4. Using the Hook Editor, write your Node.js code. As an example, we will add an extra scope. The claim's name will be `https://foo.com/claim` and its value `bar`. Copy the sample code below and paste it in the Editor.
```js
module.exports = function(client, scope, audience, context, cb) {
@@ -64,64 +68,22 @@ You can create more than one hooks per extensibility point but __only one__ can
```
This sample hook will:
- - add an arbitrary claim (`https://foo.com/claim`) to the `access_token`
+ - add an arbitrary claim (`https://foo.com/claim`) to the Access Token
- add an `extra` scope to the default scopes configured on your [API](${manage_url}/#/apis).
::: panel Custom claims namespaced format
- In order to improve compatibility for applications, Auth0 now returns profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID Tokens or Access Tokens, they must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims) to avoid possible collisions with standard OIDC claims. For example, if you choose the namespace `https://foo.com/` and you want to add a custom claim named `claim`, you would name the claim `https://foo.com/claim`, instead of just `claim`.
+ In order to improve compatibility for applications, Auth0 now returns profile information in a [structured claim format as defined by the OpenID Connect (OIDC) specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID Tokens or Access Tokens, they must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims.
:::
- 
+ 
Click __Save__ (or hit Ctrl+S/Cmd+S) and close the Editor.
5. That's it! Now you only need to test your hook. You can find detailed instructions at the [Test your Hook](#test-your-hook) paragraph.
-## Use the Auth0 CLI
-
-1. Make sure you have installed the Webtask CLI. You can find detailed instructions in the [Dashboard's Webtask page](${manage_url}/#/account/webtasks).
-
-2. Create a file with your Node.js code. For our example, we will name the file `myrule.js` and copy the following code:
-
- ```js
- module.exports = function(client, scope, audience, context, cb) {
- var access_token = {};
- access_token['https://foo.com/claim'] = 'bar';
- access_token.scope = scope;
- access_token.scope.push('extra');
- cb(null, access_token);
- };
- ```
-
-3. Create the Webtask. The command is the following:
-
- ```text
- auth0 create -t credentials-exchange -n client-credentials-exchange-hook -p ${account.namespace}-default file.js
- ```
-
- Let's break this down:
- - `auth0`: The binary to use.
- - `create`: The sub-command for creating or updating a Hook. Run in your terminal `auth0 -h` to see the rest.
- - `-t credentials-exchange`: The hook type. For this use case, set to `credentials-exchange`.
- - `-n client-credentials-exchange-hook`: The webtask's name. Set this to your preference, we chose `client-credentials-exchange-hook`.
- - `-p ${account.namespace}-default`: Your account's profile name. Get this value from _Step 2_ of the instructions on the [Dashboard's Webtask page](${manage_url}/#/account/webtasks).
- - `file.js`: The name of the file you created in the previous step.
-
- Run the command.
-
-4. You will see a message that your hook was created, but in disabled state. To enable the hook, run the command:
-
- ```text
- auth0 enable --profile ${account.namespace}-default client-credentials-exchange-hook
- ```
-
- Where `client-credentials-exchange-hook` is the name of the webtask, and `${account.namespace}-default` the name of your profile (the same as the one used in the previous step).
-
-5. That's it! Now you only need to test your hook. You can find detailed instructions at the [Test your Hook](#test-your-hook) paragraph.
-
## Test your Hook
-To test the hook you just created you need to run a Client Credentials exchange, get the `access_token`, decode it and review its contents.
+To test the hook you just created you need to run a Client Credentials exchange, get the Access Token, decode it and review its contents.
To get a token, make a `POST` request at the `https://${account.namespace}/oauth/token` API endpoint, with a payload in the following format.
@@ -130,11 +92,28 @@ To get a token, make a `POST` request at the `https://${account.namespace}/oauth
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"client_credentials\",\"client_id\": \"${account.clientId}\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"audience\": \"YOUR_API_IDENTIFIER\"}"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "client_credentials"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "audience",
+ "value": "YOUR_API_IDENTIFIER"
+ }
+ ]
}
}
```
@@ -160,11 +139,11 @@ Content-Type: application/json
}
```
-Copy the `access_token`.
+Copy the Access Token.
The easiest way to decode it and review its contents is to use the [JWT.io Debugger](https://jwt.io/#debugger-io).
-Paste your `access_token` at the left-hand editor. Automatically the JWT is decoded and its contents are displayed on the right-hand editor.
+Paste your Access Token at the left-hand editor. Automatically the JWT is decoded and its contents are displayed on the right-hand editor.

@@ -174,7 +153,7 @@ Look into the last two items of the __Payload__. Both have been set by our hook:
## Manage your Hooks
-You can disable, enable, delete or edit hooks using either the Auth0 CLI or the [dashboard]((${manage_url}/#/hooks)). You can also review your logs using the Auth0 CLI. For details, refer to the articles below.
+You can disable, enable, delete or edit hooks using either the Auth0 CLI or the [dashboard](${manage_url}/#/hooks). You can also review your logs using the Auth0 CLI. For details, refer to the articles below.
Use the Dashboard to:
- [Delete Hooks](/auth0-hooks/dashboard/create-delete)
@@ -187,9 +166,9 @@ Use the Auth0 CLI to:
- [Enable or disable Hooks](/auth0-hooks/cli/enable-disable)
- [Review Logs](/auth0-hooks/cli/logs)
-## Webtask Input Parameters
+## Input Parameters
-As you saw in our example, the webtask takes five input parameters. You can use these values for your custom logic.
+The hook takes five input parameters. You can use these values for your custom logic.
Let's see what each one contains.
@@ -222,14 +201,12 @@ Let's see what each one contains.
}
```
-- __cb__: The callback. In our example we returned the token (`cb(null, access_token)`). If you decide, however, not to issue a token, you can return `Error (cb(new Error('access denied')))`.
+- __cb__: The callback. In our example we returned the token (`cb(null, access_token)`). If you decide, however, not to issue a token, you can return `Error (cb(new Error('access denied')))`.
## Keep reading
-:::next-steps
* [What are Hooks and how you can work with them](/hooks)
* [Overview of the Client Credentials Grant](/api-auth/grant/client-credentials)
-* [How to set up a Client Credentials Grant using the Dashboard](/api-auth/config/using-the-auth0-dashboard)
-* [How to set up a Client Credentials Grant using the Management API](/api-auth/config/using-the-management-api)
+* [How to set up a Client Grant using the Dashboard](/api-auth/config/using-the-auth0-dashboard)
+* [How to set up a Client Grant using the Management API](/api-auth/config/using-the-management-api)
* [How to execute a Client Credentials Grant](/api-auth/config/asking-for-access-tokens)
-:::
diff --git a/articles/api-auth/tutorials/hybrid-flow.md b/articles/api-auth/tutorials/hybrid-flow.md
new file mode 100644
index 0000000000..c00ef7443e
--- /dev/null
+++ b/articles/api-auth/tutorials/hybrid-flow.md
@@ -0,0 +1,208 @@
+---
+description: Learn how to execute the Hybrid Flow so your app can use an ID token to access information about the user while obtaining an authorization code that can be exchanged for an Access Token.
+toc: true
+public: false
+topics:
+ - api-authentication
+ - oidc
+ - hybrid
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
+---
+# Implement the Hybrid Flow
+
+The [Hybrid Flow](/api-auth/grant/hybrid) is an OpenID Connect (OIDC) grant that enables use cases where your application can immediately use an ID token to access information about the user while obtaining an authorization code that can be exchanged for an Access Token (therefore gaining access to protected resources for an extended period of time).
+
+In this article, we will show you how you can use the Hybrid Flow in Auth0.
+
+## Prerequisites
+
+Before you begin this tutorial, please:
+
+* Check that your Application's [Grant Type property](/applications/concepts/application-grant-types) is set appropriately
+* [Register your API](/apis#how-to-configure-an-api-in-auth0) with Auth0
+
+## 1. Get the User's Authorization
+
+The first step is to get the user's consent for authentication (and possibly authorization). You can initiate the flow by sending the user to the [authorization URL](/api/authentication#authorization-code-grant)
+
+```text
+https://${account.namespace}/authorize?
+ audience=YOUR_API_AUDIENCE&
+ scope=YOUR_SCOPE&
+ response_type=YOUR_RESPONSE_TYPE&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ state=YOUR_OPAQUE_VALUE
+ nonce=NONCE
+```
+
+Where:
+
+* `audience`: The unique identifier of the API the web app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial.
+
+* `scope`: The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [API Settings](${manage_url}/#/apis)).
+
+* `response_type`: Denotes the kind of credential that Auth0 will return (code vs token). For this flow, the value must be `code id_token`, `code token`, or `code id_token token`. More specifically, `token` returns an Access Token, `id_token` returns an ID Token, and `code` returns the Authorization Code.
+
+* `client_id`: Your application's Client ID. You can find this value at your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
+
+* `state`: An opaque value the application adds to the initial request that Auth0 includes when redirecting back to the application. This value must be used by the application to prevent CSRF attacks. For more information, see [State Parameter](/protocols/oauth-state).
+
+* `redirect_uri`: The URL to which Auth0 will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the `code` URL parameter. This URL must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
+
+ ::: warning
+ Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments.
+ :::
+
+* `nonce`: A string value which will be included in the response from Auth0, [used to prevent token replay attacks](/api-auth/tutorials/nonce). It is required for `response_type=id_token token`.
+
+For example:
+
+```html
+
+ Sign In
+
+```
+
+The purpose of this call is to obtain consent from the user to invoke the API (specified in `audience`) to do certain things (specified in `scope`) on behalf of the user. Auth0 will authenticate the user and obtain consent, unless consent has been previously given.
+
+Note that if you alter the value in `scope`, Auth0 will require consent to be given again.
+
+## 2. Parsing the Response
+
+If your call to the `/authorize` endpoint is successful, Auth0 redirects you to a URL similar to the following:
+
+```text
+https://YOUR_REDIRECT_URI
+ /#access_token=ey...MhPw
+ &expires_in=7200
+ &token_type=Bearer
+ &code=AUTHORIZATION_CODE
+ &id_token=ey...qk
+```
+
+The URL contains the following components:
+
+* The redirect URI you provided for this application
+* The Authorization Code provided by Auth0
+* The ID Token
+* The Access Token
+
+If you've returned an Access Token, you'll also receive `expires_in` and `token_type` values.
+
+More specifically, here's what you will get back (depending on the value provided in `response_type`):
+
+| Response Type | Components |
+| - | - |
+| code id_token | Authorization Code, ID Token |
+| code token | Authorization Code, Access Token |
+| code id_token token | Authorization Code, ID Token, Access Token |
+
+### Access Tokens
+
+There are two ways to get Access Tokens in the Hybrid Flow.
+
+First, all calls include the `code` value in the `response_type` parameter (e.g., `code id_token`, `code token`, or `code id_token token`). As such, you'll receive an Authorization Code from Auth0 that you can then exchange for an Access Token.
+
+Second, you can explicitly request an Access Token directly by setting the `response_type` parameter to `code token` or `code id_token token`.
+
+You can therefore receive two Access Tokens for a given transaction. However, it is important to keep the two separate -- we do not recommend that an Access Token obtained when `response_type=code token` or `code token` or `code id_token token` be used to call APIs.
+
+## 3. Exchange the Authorization Code for an Access Token
+
+You can exchange the Authorization Code for an Access Token that will allow you to call the API specified in your initial authorization call.
+
+Using the Authorization Code (`code`) from the first step, you will need to `POST` to the [Token URL](/api/authentication?http#authorization-code):
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData": {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "${account.callback}"
+ }
+ ]
+ }
+}
+```
+
+Where:
+
+* `grant_type`: This must be `authorization_code`.
+* `client_id`: Your application's Client ID.
+* `client_secret`: Your application's Client Secret.
+* `code`: The Authorization Code received from the initial `authorize` call.
+* `redirect_uri`: The URL must match exactly the `redirect_uri` passed to `/authorize`.
+
+The response contains the `access_token`, `refresh_token`, `id_token`, and `token_type` values, for example:
+
+```js
+{
+ "access_token": "eyJz93a...k4laUWw",
+ "refresh_token": "GEbRxBN...edjnXbL",
+ "id_token": "eyJ0XAi...4faeEoQ",
+ "token_type": "Bearer"
+}
+```
+
+Note that `refresh_token` will only be present in the response if you included the `offline_access` scope AND enabled __Allow Offline Access__ for your API in the Dashboard. See [Refresh Tokens](/tokens/concepts/refresh-tokens) for more information.
+
+::: panel-warning Security Warning
+It is important to understand that the Authorization Code flow should only be used in cases such as a Regular Web Application where the Client Secret can be safely stored. In cases such as a Single-Page Application, the Client Secret is available to the application (in the web browser), so the integrity of the Client Secret cannot be maintained. That is why the [Implicit Flow](/flows/concepts/implicit) is more appropriate in that case.
+:::
+
+## 4. Call the API
+
+Once the Access Token has been obtained it can be used to make calls to the API by passing it as a Bearer Token in the `Authorization` header of the HTTP request:
+
+```har
+{
+ "method": "GET",
+ "url": "https://someapi.com/api",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer ACCESS_TOKEN" }
+ ]
+}
+```
+
+## 5. Verify the Token
+
+Once your API receives a request with a Bearer Access Token, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
+
+For details on the validations that should be performed, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+
+## Keep reading
+
+- [Tokens](/tokens)
+- [Refresh Tokens](/tokens/concepts/refresh-token)
+- [Configure an API in Auth0](/apis)
+- [Authorization Code Flow](/flows/concepts/auth-code)
+- [Implicit Flow](/flows/concepts/implicit)
+
diff --git a/articles/api-auth/tutorials/implicit-grant.md b/articles/api-auth/tutorials/implicit-grant.md
index 19e7340a64..07c8ccc2c5 100644
--- a/articles/api-auth/tutorials/implicit-grant.md
+++ b/articles/api-auth/tutorials/implicit-grant.md
@@ -1,11 +1,16 @@
---
-title: How to implement the Implicit Grant
-description: How to execute an Implicit Grant flow from a SPA Client application.
+description: Learn how to execute an Implicit Grant flow from a SPA Client application.
toc: true
+topics:
+ - api-authentication
+ - oidc
+ - implicit
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
---
-# How to implement the Implicit Grant
-
-<%= include('../../_includes/_pipeline2') %>
+# Implement the Implicit Grant
::: note
This tutorial will help you implement the Implicit Grant. If you are looking for some theory on the flow refer to [Call APIs from Client-side Web Apps](/api-auth/grant/implicit).
@@ -15,7 +20,7 @@ The __Implicit Grant__ is an OAuth 2.0 flow that [client-side apps](/quickstart/
Before you begin this tutorial, do the following:
-* Check that your Application's [Grant Type property](/applications/application-grant-types) is set appropriately
+* Check that your Application's [Grant Type property](/applications/concepts/application-grant-types) is set appropriately
* [Register your API](/apis#how-to-configure-an-api-in-auth0) with Auth0
## 1. Get the User's Authorization
@@ -39,19 +44,19 @@ Where:
* `audience`: The unique identifier of the API the app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial.
-* `scope`: The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must conform to a namespaced format (see panel below for more info), or any scopes supported by the target API (for example, `read:contacts`). Note that user's consent will be requested, every time the `scope` value changes. The custom scopes must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims). For more information on this, refer to the [Namespacing Custom Claims](#optional-customize-the-tokens) panel.
+* `scope`: The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Note that user's consent will be requested, every time the `scope` value changes.
-* `response_type`: Indicates the type of credentials returned in the response. For this flow you can either use `token`, to get only an `access_token`, `id_token` to get only an `id_token` (if you don't plan on accessing an API), or `id_token token` to get both an `id_token` and an `access_token`.
+* `response_type`: Indicates the type of credentials returned in the response. For this flow you can either use `token` to get only an Access Token, `id_token` to get only an ID Token (if you don't plan on accessing an API), or `id_token token` to get both an ID Token and an Access Token.
* `client_id`: Your application's Client ID. You can find this value at your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-* `redirect_uri`: The URL to which the Auth0 will redirect the user's browser after authorization has been granted by the user. The `access_token` (and optionally an `id_token`) will be available in the hash fragment of this URL. This URL must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
+* `redirect_uri`: The URL to which the Auth0 will redirect the user's browser after authorization has been granted by the user. The Access Token (and optionally an ID Token) will be available in the hash fragment of this URL. This URL must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
::: warning
Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments.
:::
-* `state`: An opaque value the application adds to the initial request that Auth0 includes when redirecting back to the application. This value must be used by the application to prevent CSRF attacks, [click here to learn more](/protocols/oauth-state).
+* `state`: An opaque value the application adds to the initial request that Auth0 includes when redirecting back to the application. This value must be used by the application to prevent CSRF attacks. For more information, see [State Parameter](/protocols/oauth-state).
* `nonce`: A string value which will be included in the response from Auth0, [used to prevent token replay attacks](/api-auth/tutorials/nonce). It is required for `response_type=id_token token`.
@@ -65,7 +70,14 @@ For example:
## 2. Extract the Access Token
-After Auth0 has redirected back to the app, you can extract the `access_token` from the hash fragment of the URL:
+After Auth0 has redirected back to the app, the hash fragment of the URL contains the following parameters:
+- `id_token`: contains an [ID Token](/tokens/concepts/id-tokens) and is present if the request parameter `response_type` included the value `id_token`, or the `scope` request parameter the value `openid`
+- `access_token`: contains an [Access Token](/tokens/concepts/access-tokens) and is present if the request parameter `response_type` included the value `token`
+- `token_type`: denotes the type of the [Access Token](/tokens/concepts/access-tokens)
+- `expires_in`: the lifetime in seconds of the Access Token. For example, the value `3600` denotes that the [Access Token](/tokens/concepts/access-tokens) will expire in one hour from the time the response was generated
+- `state`: present in the response if the `state` parameter was present in the request. Holds the exact value received from the client in the request.
+
+You can extract the `access_token`, and other parameters, from the hash fragment of the URL:
```js
function getParameterByName(name) {
@@ -84,7 +96,7 @@ function getIdToken() {
$(function () {
var access_token = getAccessToken();
- // Optional: an id_token will be returned by Auth0
+ // Optional: an ID Token will be returned by Auth0
// if your response_type argument contained id_token
var id_token = getIdToken();
@@ -114,7 +126,7 @@ $('#get-appointments').click(function(e) {
Once your API receives a request with a Bearer `access_token`, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
-For details on the validations that should be performed by the API, refer to [Verify Access Tokens](/api-auth/tutorials/verify-access-token).
+For details on the validations that should be performed by the API, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
## Optional: Customize the Tokens
@@ -124,22 +136,19 @@ If you wish to execute special logic unique to the Implicit grant, you can look
## Optional: Silent Authentication
-If you need to authenticate your users without a login page (for example, when the user is already logged in via [SSO](/sso) scenario) or get a new `access_token` (thus simulate refreshing an expired token), you can use Silent Authentication.
+If you need to authenticate your users without a login page (for example, when the user is already logged in via [Single Sign-on (SSO)](/sso) scenario) or get a new `access_token` (thus simulate refreshing an expired token), you can use Silent Authentication.
For details on how to implement this, refer to [Silent Authentication](/api-auth/tutorials/silent-authentication).
## Sample application
-For an example implementation see the [SPA + API](/architecture-scenarios/application/spa-api) architecture scenario.
+For an example implementation see the [SPA + API](/architecture-scenarios/application/spa-api) architecture scenario.
-This is a series of tutorials that describe a scenario for a fictitious company. The company wants to implement a single page web app that the employees can use to send their timesheets to the company's Timesheets API using OAuth 2.0. The tutorials are accompanied by a sample that you can access in [GitHub](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets).
+This is a series of tutorials that describe a scenario for a fictitious company. The company wants to implement a single-page web app that the employees can use to send their timesheets to the company's Timesheets API using OAuth 2.0. The tutorials are accompanied by a sample that you can access in [GitHub](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets).
## Keep reading
-::: next-steps
- [How to protect your SPA against replay attacks](/api-auth/tutorials/nonce)
- [How to configure an API in Auth0](/apis)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
- [Application Authentication for Client-side Web Apps](/application-auth/client-side-web)
-- [Tokens used by Auth0](/tokens)
-:::
+- [Tokens](/tokens)
diff --git a/articles/api-auth/tutorials/multifactor-resource-owner-password.md b/articles/api-auth/tutorials/multifactor-resource-owner-password.md
deleted file mode 100644
index 7d5c7a66d8..0000000000
--- a/articles/api-auth/tutorials/multifactor-resource-owner-password.md
+++ /dev/null
@@ -1,341 +0,0 @@
----
-title: Multifactor Authentication and Resource Owner Password
-description: How to use Multifactor Authentication with Resource Owner Password Grant.
-toc: true
----
-# Multifactor Authentication and the Resource Owner Password Grant
-
-<%= include('../../_includes/_pipeline2') %>
-
-Highly-trusted applications can use the [Resource Owner Password Grant](/api-auth/grant/password) to access an API. The flow typically involves prompting the user for username and password as credentials to be submitted to Auth0. In some scenarios, however, stronger authentication may be required. This document outlines using [multifactor authentication](/multifactor-authentication) with the [Resource Owner Password Grant](/api-auth/grant/password).
-
-## Prerequisites
-
-Before you continue, make sure that you've met the following prerequisites:
-
-1. MFA is enabled on the [Auth0 dashboard](${manage_url}). Currently, the supported providers for this flow are [Google Authenticator](/multifactor-authentication/google-auth/admin-guide#enabling-google-authenticator-for-mfa) and [Guardian](/multifactor-authentication/administrator#guardian-basics). [Duo Security](/multifactor-authentication/duo) is __not__ supported.
-
-1. An Application is configured to execute the Resource Owner Password Grant (either [password](/api-auth/tutorials/password-grant) or [password-realm](/api-auth/tutorials/password-grant#realm-support) grant types). For details on how to implement this, refer to [Execute the Resource Owner Password Grant](/api-auth/tutorials/password-grant).
-
-1. End users are enrolled in MFA.
-
-## Initiate Multifactor Authentication
-
-The flow starts by collecting end-user credentials and sending them to Auth0, as described in [Resource Owner Password Grant](/api-auth/grant/password). Both [password](/api-auth/tutorials/password-grant) and [password-realm](/api-auth/tutorials/password-grant#realm-support) flows are available.
-
-1. The user enters their credentials into the Application.
-
-2. The Application forwards the credentials to Auth0.
-
-3. Auth0 validates the credentials and executes any applicable [rules](/rules).
-
-4. If any rule triggers MFA for the current user, an error code of `mfa_required` is returned. The error will additionally contain an `mfa_token` property.
-
- ```json
- HTTP/1.1 403 Forbidden
- Content-Type: application/json
- {
- "error": "mfa_required",
- "error_description": "Multifactor authentication required",
- "mfa_token": "eyJ0eXAiOiJKV1QiLCJhbGci....D3QCiQ"
- }
- ```
-
-5. The Application will then make a request to the [MFA challenge](/api/authentication#resource-owner-password-and-mfa) endpoint, specifying the challenge types it supports. Valid challenge types are: [OTP](#challenge-type-otp), [OOB with binding method `prompt`](#challenge-type-oob-and-binding-method-prompt), and [OOB with no binding method](#challenge-type-oob-with-no-binding-method). If you already know that `otp` is supported by the end-user and you don't want to request a different factor, you can skip this and the next steps an go directly to [Challenge Type `OTP`](#challenge-type-otp) below.
-
-6. Auth0 sends a response containing the `challenge_type` derived from the types supported by the Application and the specific user. Additionally, extra information, such as `binding_method` may be included to assist in resolving the challenge and displaying the correct UI to the user.
-
-The supported challenge types are:
-
-- `otp`: A one-time password generated by an app setup with a seed or by token generation hardware. This mechanism does not require an extra channel to prove possession; you can get it directly from the app / hardware device.
-
-- `oob`: The proof of possession is done 'out of band' via a side channel. There are several different channels, including push notification-based authenticators and SMS-based authenticators. Depending on the channel and the authenticator chosen at enrollment, you may need to provide a `binding_code` used to bind the side channel and the channel used for authentication.
-
-To execute MFA, follow the next steps according to the challenge type you will use:
-
-- [OTP](#challenge-type-otp): for this challenge type, your application must prompt the end-user for an OTP code and continue the flow using the __mfa-otp__ grant type.
-
-- [OOB and binding method `prompt`](#challenge-type-oob-and-binding-method-prompt): the challenge will be sent through a side channel (such as SMS), and your application will need to prompt the user for the `binding_code` that was included as part of the challenge sent, as well as the `oob_code` received as response to this request to prove possession.
-
-- [OOB with no binding method](#challenge-type-oob-with-no-binding-method): in this case, the proof of possession will be driven entirely in a side channel (such as a push notification-based authenticator). The response will include an `oob_code` that the Application will use to periodically check for the resolution of the transaction. Continue the flow using the __mfa-oob__ grant type.
-
-## Execute Multifactor Authentication
-
-The following sections cover how to execute MFA based on the challenge type used.
-
-### Challenge Type: `OTP`
-
-
-
-For this type of challenge, the Application must get an one-time password (`otp`) code from a OTP Generator app, such as Google Authenticator or Microsoft Authenticator.
-
-::: note
-If you already know that the user supports OTP, then steps 5 and 6 above of the [Initiate Multifactor Authentication](#initiate-multifactor-authentication) section are optional.
-:::
-
-7. The Application prompts the end user to enter an OTP code.
-
-8. The end user enters their OTP into the Application.
-
-9. The Application forwards the OTP code to Auth0 using [grant_type=http://auth0.com/oauth/grant-type/mfa-otp](/api/authentication#resource-owner-password) and includes the `mfa_token` obtained in step 4 above.
-
-10. Auth0 validates the provided OTP and returns the `access_token` and the `refresh_token`.
-
-11. The Application can use the `access_token` to call the API on behalf of the end user.
-
-### Challenge Type: `OOB` with Binding Method `prompt`
-
-
-
-This challenge type, together with `prompt` binding method, indicates that the challenge will be delivered to the user using a side channel (such as SMS) and that a `binding_code` is needed to bind the side channel to the one being authenticated. The binding code is sent as part of the challenge message and it is usually an OTP-like code composed of 6 numeric digits.
-
-7. The Application prompts the user for the `binding_code` and stores the `oob_code` from step 6 for future use.
-
-8. The end user receives the challenge on the side channel and enters the `binding_code` into the Application.
-
-9. The Application forwards the `binding_code` to Auth0 using [grant_type=http://auth0.com/oauth/grant-type/mfa-oob](/api/authentication#resource-owner-password) and includes the `mfa_token` (from step 4) and `oob_code` (from step 6).
-
-10. Auth0 validates the `binding_code` and `oob_code` and returns the `access_token` and the `refresh_token`.
-
-11. The Application can use the `access_token` to call the API on behalf of the end user.
-
-### Challenge Type: `OOB` with No Binding Method
-
-
-
-In this scenario, the challenge will be sent using a side channel, however, there is no need for a `binding_code`. Currently, the only mechanism supported for this scenario is Push Notification with the Guardian Provider.
-
-7. The Application asks the user to accept the delivered challenge and keeps the `oob_code` from step 6 for future use.
-
-8. The Application polls Auth0 using [grant_type=http://auth0.com/oauth/grant-type/mfa-oob](/docs/api/authentication#resource-owner-password) and includes the `mfa_token` (from step 4) and `oob_code` (from step 6).
-
-9. Auth0 validates the provided `oob_code`, the `mfa_token` and returns:
- - `authorization_pending` error: if the challenge has not been accepted nor rejected.
- - `slow_down` error: if the polling is too frequent.
- - an `access_token` and a `refresh_token`: if the challenge has been accepted; polling should be stopped at this point.
- - `invalid_grant` error: if the challenge has been rejected; polling should be stopped at this point.
-
-10. The Application can use the `access_token` to call the API on behalf of the end user.
-
-## Using Recovery Codes
-
-::: note
-This flow is currently only available for the Guardian Provider.
-:::
-
-
-
-Some providers support using a recovery code to login in case the enrolled device is not available, or if lack of connectivity prevents receiving an OTP code or push notification.
-
-Using a recovery code is similar to using an OTP code to login. The main difference is that a new recovery code will be generated, and that the application must display this new recovery code to the user for secure storage.
-
-Steps 1-4 are the same as above.
-
-5. End user chooses to use the recovery code.
-
-6. The Application prompts the end user to enter recovery code.
-
-7. The end user enters their recovery code into the Application.
-
-8. The Application forwards the recovery code to Auth0 using [grant_type=http://auth0.com/oauth/grant-type/mfa-otp](/api/authentication#resource-owner-password) and includes the `mfa_token` from step 4.
-
-9. Auth0 validates the recovery code and returns the `access_token` and the `refresh_token`.
-
-10. The Application can use the `access_token` to call the API on behalf of the end user.
-
-## Samples
-
-The following are sample implementations involving MFA.
-
-### Resource Owner Password Grant Request
-
-```javascript
-var request = require("request");
-
-var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { grant_type: 'password',
- username: 'USERNAME',
- password: 'PASSWORD',
- audience: 'API_IDENTIFIER',
- scope: 'SCOPE',
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
-
-request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- if (body.error === 'mfa_required') {
- // Show mfa flow and give user option to go to the recovery flow (if supported)
-
- if (/* MFA Recovery is requested*/) {
- const recovery_code = // Prompt for recovery code
- mfaRecovery(body.mfa_token, recovery_code) // See MFA Recovery grant
- } else {
- mfaChallenge(body.mfa_token)
- }
- }
-});
-```
-
-### Challenge Request
-
-```javascript
-function mfaChallenge(mfa_token) {
- var options = { method: 'POST',
- url: 'https://${account.namespace}/mfa/challenge',
- headers: { 'content-type': 'application/json' },
- body:
- { mfa_token: mfa_token,
- challenge_type: 'oob otp', // Supported challenge types, space separated
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
-
- request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- if (body.challenge_type === 'otp') {
- const otp = // Prompt for otp code (see MFA OTP grant request)
- mfaOTP(mfa_token, otp)
- } else if (body.challenge_type === 'oob') {
- if (body.binding_method === 'prompt') {
- const binding_code = // Prompt for binding code (see MFA OOB with binding code grant request)
- mfaOOB(mfa_token, body.oob_code, binding_code)
- } else if (!body.binding_method) {
- // Ask the user to accept the challenge and start polling (see MFA OOB without binding code grant request)
- mfaOOB(mfa_token, body.oob_code)
- } else {
- console.error('Unsupported binding_method');
- }
- } else {
- console.error('Something went wrong');
- }
- });
-}
-```
-
-### MFA OTP Grant Request
-
-```javascript
-function mfaOTP(mfa_token, otp) {
- var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { mfa_token: mfa_token,
- otp: otp,
- grant_type: 'http://auth0.com/oauth/grant-type/mfa-otp',
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
-
- request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- if (response.statusCode === 200) {
- // The tokens returned depend on the scopes requested on the password grant request
- console.log(body.access_token, body.id_token, body.refresh_token);
- } else if (body.error === 'invalid_grant') {
- // Invalid otp code
- console.error('Invalid otp');
- } else {
- console.error('Something went wrong');
- }
- });
-}
-```
-
-### MFA OOB Grant Request
-
-```javascript
-function mfaOOB(mfa_token, oob_code, /* optional */ binding_code) {
- makeOOBGrantRequest(mfa_token, oob_code, binding_code, function(error, result) {
- if (error) { throw error; }
-
- if (result.state === 'authorization_pending') {
- // Poll every 10 seconds
- setTimeout(() => makeOOBGrantRequest(mfa_token, oob_code, binding_code), 10000);
- } else if (result.state === 'authorized') {
- console.log(result.body.access_token, result.body.id_token, result.body.refresh_token);
- } else {
- console.error('You are not authorized')
- }
- });
-}
-
-function makeOOBGrantRequest(mfa_token, oob_code, /* optional */ binding_code, cb) {
- var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { mfa_token: mfa_token,
- oob_code: oob_code,
- binding_code: binding_code, // Only when binding_method = prompt
- grant_type: 'http://auth0.com/oauth/grant-type/mfa-oob',
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
-
- request(options, function (error, response, body) {
- if (error) { return cb(error); }
-
- if (response.statusCode === 200) {
- // The tokens returned depend on the scopes requested on the password grant request
- cb(null, { state: 'authorized', body });
- } else if (body.error === 'invalid_grant') {
- // Invalid otp code
- cb(null, { state: 'not_authorized' });
- } else if (body.error === 'authorization_pending') {
- cb(null, { state: 'authorization_pending' });
- } else if (body.error === 'slow_down') {
- // You are polling too fast, slow down the polling rate,
- // You may want to check rate-limiting headers to manage your polling rate
- setTimeout(() => cb({ state: 'authorization_pending' }), 20000);
- } else {
- cb(new Error('Something went wrong'))
- }
- });
-}
-```
-
-### MFA Recovery Grant Request
-
-```javascript
-function mfaRecovery(mfa_token, recovery_code) {
- var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { mfa_token: mfa_token,
- recovery_code: recovery_code,
- otp: otp,
- grant_type: 'http://auth0.com/oauth/grant-type/mfa-recovery-code',
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
-
- request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- if (response.statusCode === 200) {
- console.log('Please store this new recovery code safely -- the previous code will no longer work.', body.recovery_code)
-
- // The tokens returned depend on the scopes requested on the password grant request
- console.log(body.access_token, body.id_token, body.refresh_token);
- } else if (body.error === 'invalid_grant') {
- // Invalid otp code
- console.error('Invalid recovery_code');
- } else {
- console.error('Something went wrong');
- }
- });
-}
-```
-
-## MFA API
-
-Please see the [MFA API section](/multifactor-authentication/api) for detailed information on Auth0's MFA API endpoints.
diff --git a/articles/api-auth/tutorials/nonce.md b/articles/api-auth/tutorials/nonce.md
index d72074bec1..c83e542ae8 100644
--- a/articles/api-auth/tutorials/nonce.md
+++ b/articles/api-auth/tutorials/nonce.md
@@ -1,29 +1,52 @@
---
-description: How to securely generate and validate a cryptographic nonce for use with the Implicit Grant
+description: How to securely generate and validate a cryptographic nonce for use with the Implicit Grant.
+topics:
+ - api-authentication
+ - oidc
+ - implicit
+ - nonce
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
---
-# Mitigate replay attacks when using the Implicit Grant
+# Mitigate Replay Attacks When Using the Implicit Flow
-<%= include('../../_includes/_pipeline2') %>
+To mitigate replay attacks when using the [Implicit Flow](/flows/concepts/implicit), a nonce must be sent on authentication requests [as required by the OpenID Connect (OIDC) specification](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest).
-When using the [Implicit Grant](/api-auth/grant/implicit), a [cryptographic nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) must be sent on authentication requests in order to mitigate replay attacks [as required by the OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest).
-The nonce is generated by the application, sent as a `nonce` query string parameter in the authentication request, and included in the ID Token response from Auth0.
-This allows applications to correlate the ID Token response from Auth0 with the initial authentication request.
+The nonce is generated by the application, sent as a `nonce` query string parameter in the authentication request, and included in the ID Token response from Auth0. This allows applications to correlate the ID Token response from Auth0 with the initial authentication request.
+
+For more information on where to include the nonce, see [Call API Using the Implicit Flow](/flows/guides/implicit/call-api-implicit).
+
+::: note
+[Auth0.js](/libraries/auth0js) manages `state` and `nonce` parameters for you when using cross-origin authentication.
+:::
## Generate a cryptographically random nonce
-[Modern browsers](http://caniuse.com/#feat=cryptography) can use the [Web Crypto API](https://www.w3.org/TR/WebCryptoAPI/) to generate cryptographically secure random strings for use as nonces.
+One way to generate a cryptographically random nonce is to use a tool like [Nano ID](https://github.com/ai/nanoid) or similar. This does require you to bundle the tool with your JavaScript code, however. If that's not possible, you can take advantage of the fact that [modern browsers](http://caniuse.com/#feat=cryptography) can use the [Web Crypto API](https://www.w3.org/TR/WebCryptoAPI/) to generate cryptographically secure random strings for use as nonces.
```js
function randomString(length) {
- var bytes = new Uint8Array(length);
- var random = window.crypto.getRandomValues(bytes);
- var result = [];
- var charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._~'
- random.forEach(function (c) {
- result.push(charset[c % charset.length]);
- });
- return result.join('');
+ var charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._'
+ result = ''
+
+ while (length > 0) {
+ var bytes = new Uint8Array(16);
+ var random = window.crypto.getRandomValues(bytes);
+
+ random.forEach(function(c) {
+ if (length == 0) {
+ return;
+ }
+ if (c < charset.length) {
+ result += charset[c];
+ length--;
+ }
+ });
+ }
+ return result;
}
```
diff --git a/articles/api-auth/tutorials/password-grant.md b/articles/api-auth/tutorials/password-grant.md
index a8d5652461..f8ef39ba44 100644
--- a/articles/api-auth/tutorials/password-grant.md
+++ b/articles/api-auth/tutorials/password-grant.md
@@ -1,23 +1,31 @@
---
-title: How to implement the Resource Owner Password Grant
-description: Step-by-step guide on how to implement the OAuth 2.0 Resource Owner Password Grant
+description: Learn how to implement the OAuth 2.0 Resource Owner Password Grant
toc: true
+topics:
+ - api-authentication
+ - oidc
+ - resource-owner-password
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
---
-# How to implement the Resource Owner Password Grant
+# Implement the Resource Owner Password Grant
-<%= include('../../_includes/_pipeline2') %>
+<%= include('../_includes/_ropg-warning') %>
-In this tutorial we will go through the steps required to implement the Resource Owner Password Grant.
-
-You should use this flow **only if** the following apply:
-- The application is absolutely trusted with the user's credentials. For [client side](/api-auth/grant/implicit) applications and [mobile apps](/api-auth/grant/authorization-code-pkce) we recommend using web flows instead.
-- Using a redirect-based flow is not possible. If this is not the case and redirects are possible in your application you should use the [Authorization Code Grant](/api-auth/grant/authorization-code) instead.
+In this tutorial, we will go through the steps required to implement the Resource Owner Password Grant flow.
## Before you start
-* Check that your application's [grant type property](/applications/application-grant-types) is set appropriately
-* [Register the API](/apis#how-to-configure-an-api-in-auth0) with Auth0
-* Check that the [Default Audience and/or Default Directory](/dashboard/dashboard-tenant-settings#api-authorization-settings) has been set appropriately
+* Check that your application's grant type is set to "Password". To set an application's grant type:
+ 1. Go to the [Dashboard](${manage_url}) and select **Applications**
+ 2. Choose your application from the list
+ 3. On the **Settings** page scroll down to **Advanced Settings**
+ 4. Select the **Grant Types** tab
+ 5. Enable the "Password" grant
+* [Register the API](/apis#how-to-configure-an-api-in-auth0) with Auth0.
+* Update or disable any [rules](/rules) so they only impact specific connections. If you get an `'access_denied'` error when testing the Password Grant, this could be due to an access control rule.
## Configure your tenant
@@ -38,11 +46,40 @@ In order to execute the flow the application needs to acquire the Resource Owner
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"password\",\"username\": \"user@example.com\",\"password\": \"pwd\",\"audience\": \"https://someapi.com/api\", \"scope\": \"read:sample\", \"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\"}"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "password"
+ },
+ {
+ "name": "username",
+ "value": "user@example.com"
+ },
+ {
+ "name": "password",
+ "value": "pwd"
+ },
+ {
+ "name": "audience",
+ "value": "YOUR_API_IDENTIFIER"
+ },
+ {
+ "name": "scope",
+ "value": "read:sample"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ }
+ ]
}
}
```
@@ -55,9 +92,9 @@ Where:
* `audience`: The **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial.
* `client_id`: Your application's Client ID. You can find this value at the [Settings tab of the Machine to Machine Application](${manage_url}/#/applications).
* `client_secret`: Your application's Client Secret. You can find this value at the [Settings tab of the Machine to Machine Application](${manage_url}/#/applications). This is required when the **Token Endpoint Authentication Method** field at your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings) is `Post` or `Basic`. Do not set this parameter if your application is not highly trusted (for example, SPA).
-* `scope`: String value of the different [scopes](/scopes) the application is asking for. Multiple scopes are separated with whitespace.
+* `scope`: String value of the different scopes the application is asking for. Multiple scopes are separated with whitespace.
-The response contains a [signed JSON Web Token](/jwt), the token's type (which is `Bearer`), and in how much time it expires in [Unix time](https://en.wikipedia.org/wiki/Unix_time) (86400 seconds, which means 24 hours).
+The response contains a signed JSON Web Token (JWT), the token's type (which is `Bearer`), and in how much time it expires in [Unix time](https://en.wikipedia.org/wiki/Unix_time).
```js
{
@@ -70,18 +107,18 @@ The response contains a [signed JSON Web Token](/jwt), the token's type (which i
In case the scopes issued to the application differ from the scopes requested, a `scope` parameter will be included in the response JSON, listing the issued scopes.
::: panel Password grant and standard scopes
-If **no** API scopes (such as `read:notes`) are included in the request, all API scopes (such as `read:notes`, `create:notes`, and so on.) are included in the `access_token`.
+If **no** API scopes (such as `read:notes`) are included in the request, all API scopes (such as `read:notes`, `create:notes`, and so on.) are included in the Access Token.
If only the `openid` scope is included in the request, all `openid` standard scopes will be returned, such as `openid profile email address phone`.
In these cases, the `scope` parameter will be included in the response, listing the issued scopes. This happens because a password is equal to full access and hence any password-based exchange gives access to all scopes.
:::
::: panel How to get the user's claims
-If you need the user's claims you can include the scope `openid` to your request. If the API uses `RS256` as the signing algorithm, the `access_token` will now also include `/userinfo` as a valid audience. You can use this `access_token` to invoke the [/userinfo endpoint](/api/authentication#get-user-info) and retrieve the user's claims.
+If you need the user's claims you can include the scope `openid` to your request. If the API uses `RS256` as the [signing algorithm](/tokens/concepts/signing-algorithms), the Access Token will now also include `/userinfo` as a valid audience. You can use this Access Token to invoke the [/userinfo endpoint](/api/authentication#get-user-info) and retrieve the user's claims.
:::
-### Realm Support
+### Realm support
-A extension grant that offers similar functionality with the **Resource Owner Password Grant**, including the ability to indicate a specific realm, is the `http://auth0.com/oauth/grant-type/password-realm`.
+An extension grant that offers similar functionality to ROPG, including the ability to indicate a specific realm, is the `http://auth0.com/oauth/grant-type/password-realm`.
Realms allow you to keep separate user directories and specify which one to use to the token endpoint.
@@ -94,22 +131,55 @@ To use this variation you will have to change the following request parameters:
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"http://auth0.com/oauth/grant-type/password-realm\",\"username\": \"user@example.com\",\"password\": \"pwd\",\"audience\": \"https://someapi.com/api\", \"scope\": \"read:sample\", \"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"realm\": \"employees\"}"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "http://auth0.com/oauth/grant-type/password-realm"
+ },
+ {
+ "name": "username",
+ "value": "user@example.com"
+ },
+ {
+ "name": "password",
+ "value": "pwd"
+ },
+ {
+ "name": "audience",
+ "value": "YOUR_API_IDENTIFIER"
+ },
+ {
+ "name": "scope",
+ "value": "read:sample"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "realm",
+ "value": "employees"
+ }
+ ]
}
}
```
::: panel Auth0 Connections as Realms
-You can configure Auth0 Connections as realms, as long as they support active authentication. This includes [Database](/connections/database), [Passwordless](/connections/passwordless), [Active Directory/LDAP](/connections/enterprise/active-directory), [Windows Azure AD](/connections/enterprise/azure-active-directory) and [ADFS](/connections/enterprise/adfs) connections.
+You can configure Auth0 Connections as realms, as long as they support active authentication. This includes [Database](/connections/database), [Passwordless](/connections/passwordless), [Active Directory/LDAP](/connections/enterprise/active-directory-ldap), [Windows Azure AD](/connections/enterprise/azure-active-directory) and [ADFS](/connections/enterprise/adfs) connections.
:::
## Use the token
-Once the `access_token` has been obtained it can be used to make calls to the Resource Server by passing it as a Bearer Token in the `Authorization` header of the HTTP request:
+Once the Access Token has been obtained it can be used to make calls to the Resource Server by passing it as a Bearer Token in the `Authorization` header of the HTTP request:
```har
{
@@ -124,9 +194,9 @@ Once the `access_token` has been obtained it can be used to make calls to the Re
## Verify the token
-Once your API receives a request with a Bearer `access_token`, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
+Once your API receives a request with a Bearer Access Token, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request _must_ be rejected.
-For details on the validations that should be performed by the API, refer to [Verify Access Tokens](/api-auth/tutorials/verify-access-token).
+For details on the validations that should be performed by the API, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
## Optional: Customize the Tokens
@@ -136,7 +206,7 @@ If you wish to execute special logic unique to the Password exchange, you can lo
## Optional: Configure MFA
-In case you need stronger authentication, than username and password, you can configure MultiFactor Authentication (MFA) using the Resource Owner Password Grant. For details on how to implement this refer to [Multifactor Authentication and Resource Owner Password](/api-auth/tutorials/multifactor-resource-owner-password).
+In case you need stronger authentication, than username and password, you can configure multi-factor authentication (MFA) using the Resource Owner Password Grant. For details on how to implement this refer to [Multi-factor Authentication and Resource Owner Password](/mfa/guides/mfa-api/multifactor-resource-owner-password).
## Optional: Configure Anomaly Detection
@@ -144,9 +214,6 @@ When using this flow from server-side applications, some anomaly detection featu
## Keep reading
-::: next-steps
* [Call APIs from Highly Trusted Applications](/api-auth/grant/password)
* [How to configure an API in Auth0](/apis)
-* [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
-* [Tokens used by Auth0](/tokens)
-:::
+* [Tokens](/tokens)
diff --git a/articles/api-auth/tutorials/represent-multiple-apis.md b/articles/api-auth/tutorials/represent-multiple-apis.md
index 6f81456900..5eaf10b709 100644
--- a/articles/api-auth/tutorials/represent-multiple-apis.md
+++ b/articles/api-auth/tutorials/represent-multiple-apis.md
@@ -1,106 +1,126 @@
---
- description: How to use multiple APIs and represent them as a single API in Auth0.
+
+description: Learn how to use a single logical API in Auth0 to represent and control access to multiple APIs.
+topics:
+ - api-authentication
+ - oidc
+ - apis
+ - scopes
+ - permissions
+contentType: how-to
+useCase:
+ - secure-api
+ - call-api
---
-# How to Represent Multiple APIs Using a Single Auth0 API
+# Represent Multiple APIs Using a Single Logical API
-To simplify your authentication process, you can create a single [API](/apis) using the Auth0 Dashboard to represent all of your existing APIs. Doing this allows you to implement just one authentication flow. You can then control access to the individual APIs by assigning the appropriate scopes.
+If you have multiple distinct API implementations that are all logically a part of the same API, you can simplify your authorization process by representing them with a single logical [API](/apis) in the Auth0 Dashboard. Doing this allows you to implement just one authorization flow, while still controlling access to the individual APIs by assigning the appropriate scopes.
-This article shows you how to use and represent multiple APIs as a single Resource Server in Auth0 using a [sample application you can download](https://github.com/auth0-samples/auth0-api-auth-implicit-sample) if you would like to follow along as you read.
+This tutorial explains how to use and represent multiple APIs as a single Resource Server in Auth0. As a learning tool, we provide a sample application that you can follow along with as you read.
## The Sample Application
-The sample application contains:
+The sample application uses a microservices architecture and contains:
+
+* 1 Single-Page Application (SPA)
+* 2 APIs (services), called `contacts` and `calendar`
-* 1 Single Page Application (SPA);
-* 2 APIs (called `contacts` and `calendar`).
+We will represent the two APIs using just one Auth0 API called `Organizer Service`. We will then create two scopes to demonstrate how you can use the [Implicit Flow](/flows/concepts/implicit) to access the `calendar` and `contacts` APIs from the SPA.
-We will represent the two APIs using just one Auth0 API called `Organizer Service`. We will then create two namespaced scopes to demonstrate how you can use the [Implicit Grant](/api-auth/grant/implicit) to access the `calendar` and `contacts` APIs from the SPA. The SPA also uses [Lock](/libraries/lock) to implement the signin screen.
+## Prerequisites
-Please see the `README` for additional information on setting up the sample on your local environment.
+Before beginning this tutorial:
-## The Auth0 Application
+* [Register your Application with Auth0](/dashboard/guides/applications/register-app-spa)
+ * Select an **Application Type** of **Single-Page App**.
+ * Add **Allowed Callback URLs** of `http://localhost:3000` and `http://localhost:3000/callback.html`.
+* [Download the sample application](https://github.com/auth0-samples/auth0-api-auth-implicit-sample), so you can follow along as you read. Please see the `README` for additional information on setting up the sample on your local environment.
-If you don't already have an Auth0 Application (of type **Single Page Web Applications**) with the **OIDC Conformant** flag enabled, you'll need to create one. This represents your application.
+## Steps
-1. In the [Auth0 Dashboard](${manage_url}), click on [Applications](${manage_url}/#/applications) in the left-hand navigation bar. Click **Create Application**.
-2. The **Create Application** window will open, allowing you to enter the name of your new Application. Choose **Single Page Web Applications** as the **Application Type**. When done, click on **Create** to proceed.
-3. Navigate to the [Auth0 Application Settings](${manage_url}/#/applications/${account.clientId}/settings) page. Add `http://localhost:3000` and `http://localhost:3000/callback.html` to the Allowed Callback URLs field of your [Auth0 Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-4. Scroll to the bottom of the [Settings](${manage_url}/#/applications/${account.clientId}/settings) page, where you'll find the *Advanced Settings* section. Under the *OAuth* tab, enable the **OIDC Conformant** Flag under the *OAuth* area of *Advanced Settings*.
+1. [Enable a Connection for your Application](#enable-a-connection-for-your-application): Configure a source of users for your new application.
+2. [Create a test user](#create-a-test-user): Associate a test user with your new connection.
+3. [Register a logical API in Auth0](#register-a-logical-api-in-auth0): Register a single logical API to represent your multiple APIs.
+4. [Configure scopes for the logical API](#configure-scopes-for-the-logical-API): Create the scopes that will allow the logical API to represent your multiple APIs.
+5. [Grant access to the logical API](#grant-access-to-the-logical-api): Configure the login link in your sample application, initiate the authorization flow, and extract the Access Token to be used to call your multiple APIs.
+Optional: [Implement Single Logout (SLO) or Single Sign-on (SSO)](#implement-single-log-out-slo-or-single-sign-on-sso)
-### Enable a Connection for Your Application
+## Enable a connection for your Application
-[Connections](/identityproviders) are sources of users to your application, and if you don't have a sample Connection you can use with your newly-created Application, you will need to configure one. For the purposes of this sample, we'll create a simple [Database Connection](/connections/database) that asks only for the user's email address and a password.
+You will need a source of users for your newly-registered application, so you will need to configure a [Connection](/identityproviders). For the purpose of this sample, we'll create a simple [Database Connection](/connections/database) that asks only for the user's email address and a password.
-1. In the [Auth0 Dashboard](${manage_url}), click on [Connections > Database](${manage_url}/#/connections/database) in the left-hand navigation bar. Click **Create DB Connection**.
+1. Navigate to the [Auth0 Dashboard](${manage_url}), and click on [Connections > Database](${manage_url}/#/connections/database) in the left-hand nav. Click **Create DB Connection**.
2. The **Create DB Connection** window will open. Provide a **Name** for your Connection, and click **Create** to proceed.
-3. Once your Connection is ready, click over to the *Applications* tab, and enable the Connection for your Application.
+3. Click the **Applications** tab, and enable the Connection.
-### Create a Test User
+## Create a test user
-If you're working with a newly-created Connection, you won't have any users associated with the Connection. Before you can test your sample's login process, you'll need to create and associate a user with your Connection.
+Since you're working with a newly-created Connection, there won't be any users associated with it. Before we can test the sample application's login process, we'll need to create and associate a user with the Connection.
-1. In the [Auth0 Dashboard](${manage_url}), click on [Users](${manage_url}/#/users) in the left-hand navigation bar. Click **Create User**.
+1. Navigate to the [Auth0 Dashboard](${manage_url}), and click on [Users](${manage_url}/#/users) in the left-hand nav. Click **Create User**.
2. Provide the requested information about the new user (**email address** and **password**), and select your newly-created **Connection**.
-3. Click **Save** to proceed.
-
-## Create the Auth0 API
+3. Click **Save**.
-Log in to your Auth0 Dashboard, and navigate to the APIs section.
+## Register a logical API in Auth0
-::: note
- For detailed information on working with APIs in the Dashboard, refer to APIs.
-:::
+Register a single logical [API](/apis) that you will use to represent the multiple APIs contained within the sample application.
-Click **Create API**.
+1. Navigate to the [Auth0 Dashboard](${manage_url}), and click on [APIs](${manage_url}/#/apis) in the left-hand nav. Click **Create API**.

-You will be prompted to provide a **name** and **identifier**, as well as choose the **signing algorithm**, for your new API.
+2. When prompted, provide a **name** and **identifier** for the new API, and choose the **signing algorithm** for the tokens obtained for this API.
-For the purposes of this article, we'll call our API `Organizer Service` and set its unique identifier to `organize`. By default, the signing algorithm for the tokens this API issues is **RS256**, which we will leave as is.
+For the purpose of this sample, we'll call our API `Organizer Service` and set its unique identifier to `organize`. By default, the [signing algorithm](/tokens/concepts/signing-algorithms) for the tokens obtained for this API is **RS256**, which we will leave as is.
-
+When finished, click **Create**.
-Once you've provided the required details, click **Create** to proceed.
+
-### Configure the Auth0 API
+## Configure scopes for the logical API
-After Auth0 creates your API, you'll be directed to its *Quick Start* page. At this point, you'll need to create the appropriate **Scopes**, which you can do via the *Scopes* page.
+To allow the logical API to represent the APIs included within the sample application, you will need to create the proper scopes.
-
+Scopes allow you to define which API actions will be accessible to calling applications. One scope will represent one API/action combination.
-Scopes allow you to define the API data accessible to your applications. You'll need one scope for each API represented and action. For example, if you want to `read` and `delete` from an API called `samples`, you'll need to create the following scopes:
+For example, if you want calling applications to be able to `read` and/or `delete` from one API called `samples` and another one called `examples`, you would need to create the following permissions:
* `read:samples`
* `delete:samples`
+* `read:examples`
+* `delete:examples`
-For our sample application, we'll add two scopes:
+You can think of each one as a microservice.
-* `read:calendar`;
-* `read:contacts`.
+1. In your newly-created logical API, click the **Scopes** (or **Permissions**) tab.
-You can think of each one as a microservice.
+
-
+2. Add two scopes:
+
+* `read:calendar`
+* `read:contacts`
+
+**Save** your changes.
-Add these two scopes to your API and **Save** your changes.
+
-## Grant Access to the Auth0 API
+## Grant access to the logical API
-You are now ready to provide access to your APIs by granting Access Tokens to the Auth0 API. By including specific scopes, you can control an application to some or all of the APIs represented by the Auth0 API.
+You are now ready to provide access to your APIs by allowing the logical API to obtain Access Tokens. By including the necessary scopes, you can control an application's access to the APIs represented by the logical API.
:::panel Authorization Flows
-The rest of this article covers use of the [Implicit Grant](/api-auth/grant/implicit) to reflect the sample. You can, however, use whichever flow best suits your needs.
+The rest of this article covers use of the [Implicit Flow](/flows/concepts/implicit) to reflect the sample. However, you can use whichever flow best suits your needs. For example:
-* If you have a **Machine to Machine Application**, you can authorize it to request Access Tokens to your API by executing a [client credentials exchange](/api-auth/grant/client-credentials).
-* If you are building a **Native App**, you can implement the use of [Authorization Codes using PKCE](/api-auth/grant/authorization-code-pkce).
+* If you have a **Machine-to-Machine Application**, you can authorize it to request Access Tokens for your API by executing a [Client Credentials Flow](/flows/concepts/client-credentials).
+* If you are building a **Native App**, you can implement the [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce).
For a full list of available Authorization flows, see [API Authorization](/api-auth).
:::
-The app initiates the flow and redirects the browser to Auth0 (specifically to the `/authorize` endpoint), so the user can authenticate.
+1. The user clicks Login within the SPA, and the app redirects the user to the Auth0 Authorization Server (`/authorize` endpoint).
```text
https://YOUR_AUTH0_DOMAIN/authorize?
@@ -112,21 +132,21 @@ redirect_uri=http://localhost:3000&
nonce=NONCE
```
-For additional information on the call's parameters, refer to the [docs on executing an implementing the Implicit Grant](/api-auth/tutorials/implicit-grant#1-get-the-user-s-authorization).
-
-The SPA executes this call whenever the user clicks **Login**.
+::: note
+For additional information on the call's parameters, refer to our tutorial, [Call Your API Using the Implicit Flow](/flows/guides/implicit/call-api-implicit#authorize-the-user).
+:::

-Lock handles the login process.
+2. Your Auth0 Authorization Server redirects the user to the login page, where the user authenticates using one of the configured login options.

-Next, Auth0 authenticates the user. If this is the first time the user goes through this flow, they will be asked to consent to the scopes that are given to the Application. In this case, the user's asked to consent to the app reading their contacts and calendar.
+3. If this is the first time the user has been through this flow, they see a consent prompt listing the permissions Auth0 will give to the SPA. In this case, the user is asked to consent to the app reading their contacts and calendar.

-If the user consents, Auth0 continues the authentication process, and upon completion, redirects them back to the app with an `access_token` in the hash fragment of the URI. The app can now extract the tokens from the hash fragment. In a Single Page Application (SPA) this is done using JavaScript.
+4. If the user consents, Auth0 redirects the user back to the SPA with tokens in the hash fragment of the URI. The SPA can now extract the tokens from the hash fragment using JavaScript and use the Access Token to call your APIs on behalf of the user.
```js
function getParameterByName(name) {
@@ -139,8 +159,11 @@ function getAccessToken() {
}
```
-The app can then use the `access_token` to call the API on behalf of the user.
-
-After logging in, you can see buttons that allow you to call either of your APIs.
+In our sample, after you successfully log in, you will see buttons that allow you to call either of your APIs using the Access Token obtained from the logical API.

+
+
+## Implement Single Logout (SLO) or Single Sign-on (SSO)
+
+<%= include('../../_includes/_checksession_polling') %>
diff --git a/articles/api-auth/tutorials/silent-authentication.md b/articles/api-auth/tutorials/silent-authentication.md
index f887fb8fdc..cb23a93b46 100644
--- a/articles/api-auth/tutorials/silent-authentication.md
+++ b/articles/api-auth/tutorials/silent-authentication.md
@@ -1,106 +1,143 @@
---
-description: How to keep users logged in to your application
+description: Learn how to keep users logged in to your application using silent authentication.
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - silent-authentication
+contentType: how-to
+useCase:
+ - secure-api
+ - call-api
---
-# Silent Authentication
+# Configure Silent Authentication
-<%= include('../../_includes/_pipeline2') %>
+The OpenID Connect protocol supports a `prompt=none` parameter on the authentication request that allows applications to indicate that the authorization server must not display any user interaction (such as authentication, consent or MFA). Auth0 will either return the requested response back to the application or return an error if the user is not already authenticated, or that some type of consent or prompt is required before proceeding.
-There are two main participants involved in a [single sign-on (SSO)](/sso) scenario: an Authorization Server (Auth0), and multiple applications.
+Use of the [Implicit Flow](/flows/concepts/implicit) in SPAs presents security challenges requiring explicit mitigation strategies. You can use the [Authorization Code Flow with PKCE](/flows/concepts/auth-code-pkce) in conjunction with Silent Authentication to renew sessions in SPAs.
-For privacy reasons, applications cannot query Auth0 directly to determine if a user has logged in via SSO. This means that users must be redirected to Auth0 for SSO authentication.
+<%= include('../../_includes/_refresh_token_rotation_recommended.md') %>
-However, redirecting users away from your application is usually considered disruptive and should be avoided, from a UX perspective. **Silent authentication** lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page.
+## Initiate Silent Authentication requests
-## Initiate a Silent Authentication request
-
-To initiate a silent authentication request, add the `prompt=none` parameter when you redirect a user to the [`/authorize` endpoint of Auth0's authentication API](/api/authentication#authorize-client).
+To initiate a silent authentication request, add the `prompt=none` parameter when you redirect a user to the [`/authorize` endpoint of Auth0's authentication API](/api/authentication#authorize-application). (The individual parameters on the authentication request will vary depending on the specific needs of your app.
+)
For example:
```text
GET https://${account.namespace}/authorize
- ?response_type=code&
+ ?response_type=id_token token&
client_id=...&
redirect_uri=...&
state=...&
scope=openid...&
+ nonce=...&
+ audience=...&
+ response_mode=...&
prompt=none
```
-::: note
- The specific parameters on the authentication request will depend on what kind of application is authenticating (regular web application, single page app), and so forth).
-:::
-
-The `prompt=none` parameter will cause Auth0 to immediately redirect to the specified `redirect_uri` (callback URL) with two possible responses:
-
-* A successful authentication response if the user was already logged in via SSO
-* An error response if the user is not logged in via SSO and therefore cannot be silently authenticated
+The `prompt=none` parameter causes Auth0 to immediately send a result to the specified `redirect_uri` (callback URL) using the specified `response_mode` with one of two possible responses: success or error.
::: note
Any applicable [rules](/rules) will be executed as part of the silent authentication process.
:::
-### Successful authentication response
+### Successful authentication responses
-If the user was already logged in via SSO, Auth0 will respond exactly as if the user had authenticated manually through the SSO login page.
+If the user was already logged in to Auth0 and no other interactive prompts are required, Auth0 will respond exactly as if the user had authenticated manually through the login page.
-For example, when using the [Authorization Code Grant](/api-auth/grant/authorization-code) (`response_type=code`, used for regular web applications), Auth0 will respond with an authorization code that can be exchanged for an ID Token and optionally an Access Token:
+For example, when using the Implicit Flow, (`response_type=id_token token`, used for single-page applications), Auth0 will respond with the requested tokens:
```text
GET ${account.callback}
- ?code=...&
+ #id_token=...&
+ access_token=...&
state=...&
expires_in=...
```
-Note that this response is indistinguishable from a login performed directly without the `prompt=none` parameter.
+This response is indistinguishable from a login performed directly without the `prompt=none` parameter.
-### Error response
+### Error responses
-If the user was not logged in via SSO or their SSO session had expired, Auth0 will redirect to the specified `redirect_uri` (callback URL) with an error:
+If the user was not logged in via Single Sign-on (SSO) or their SSO session had expired, Auth0 will redirect to the specified `redirect_uri` (callback URL) with an error:
```
GET https://your_callback_url/
- ?error=ERROR_CODE&
+ #error=ERROR_CODE&
error_description=ERROR_DESCRIPTION&
state=...
```
-When using the [Authorization Code Grant](/api-auth/grant/authorization-code), the error response parameters are returned in the query string. When using the [Implicit Grant](/api-auth/grant/implicit), they are returned in the hash fragment instead.
-
The possible values for `ERROR_CODE` are defined by the [OpenID Connect specification](https://openid.net/specs/openid-connect-core-1_0.html#AuthError):
-* `login_required`: The user was not logged in at Auth0, so silent authentication is not possible
-* `consent_required`: The user was logged in at Auth0, but needs to give consent to authorize the application
-* `interaction_required`: The user was logged in at Auth0 and has authorized the application, but needs to be redirected elsewhere before authentication can be completed; for example, when using a [redirect rule](/rules/redirect).
+| Response | Description |
+| -- | -- |
+| `login_required` | The user was not logged in at Auth0, so silent authentication is not possible. This error can occur based on the way the tenant-level **Log In Session Management** settings are configured; specifically, it can occur after the time period set in the **Require log in after** setting. See [Configure Session Lifetime Settings](/dashboard/guides/tenants/configure-session-lifetime-settings) for details. |
+| `consent_required` | The user was logged in at Auth0, but needs to give consent to authorize the application. |
+| `interaction_required` | The user was logged in at Auth0 and has authorized the application, but needs to be redirected elsewhere before authentication can be completed; for example, when using a [redirect rule](/rules/redirect). |
If any of these errors are returned, the user must be redirected to the Auth0 login page without the `prompt=none` parameter to authenticate.
## Renew expired tokens
-Access Tokens are opaque to applications. This means that applications are unable to inspect the contents of Access Tokens to determine their expiration date.
+You can make a silent authentication request to get new tokens as long as the user still has a valid session at Auth0. The [`checkSession` method from auth0.js](/libraries/auth0js#using-checksession-to-acquire-new-tokens) uses a silent token request in combination with `response_mode=web_message` for SPAs so that the request happens in a hidden iframe. With SPAs, Auth0.js handles the result processing (either the token or the error code) and passes the information through a callback function provided by the application. This results in no UX disruption (no page refresh or lost state).
+
+::: note
+See [Renew Tokens When Using Safari](/api-auth/token-renewal-in-safari) for other important limitations and workarounds with the Safari browser.
+:::
+
+### Access Token expiration
+
+Access Tokens are opaque to applications. This means that applications are unable to inspect the contents of Access Tokens to determine their expiration date.
There are two options to determine when an Access Token expires:
-1. Read the `expires_in` response parameter returned by Auth0
-2. Ignore expiration dates altogether. Instead, try to renew the Access Token if your API rejects a request from the application (such as with a 401).
+* Read the `expires_in` response parameter returned by Auth0.
+* Ignore expiration dates altogether. Instead, renew the Access Token if your API rejects a request from the application (such as with a 401).
-In the case of the [Implicit Grant](/api-auth/grant/implicit), the `expires_in` parameter is returned by Auth0 as a hash parameter following a successful authentication. For the [Authorization Code Grant](/api-auth/grant/code), it is returned to the backend server when performing the authorization code exchange.
+In the case of the [Implicit Flow](/flows/concepts/implicit), the `expires_in` parameter is returned by Auth0 as a hash parameter following a successful authentication. In the [Authorization Code Flow](/flows/concepts/auth-code), it is returned to the backend server when performing the authorization code exchange.
The `expires_in` parameter indicates how many seconds the Access Token will be valid for, and can be used to anticipate expiration of the Access Token.
-When the Access Token has expired, silent authentication can be used to retrieve a new one without user interaction, assuming the user's SSO session has not expired.
+### Error response
-In the case of single-page applications, the [`checkSession` method from auth0.js](/libraries/auth0js#using-checksession-to-acquire-new-tokens) can be used to perform silent authentication within a hidden iframe, which results in no UX disruption at all.
+You may receive the `timeout` error response which indicates that timeout during executing `web_message` communication has occurred. This error is typically associated with fallback to cross-origin authentication. To resolve, make sure to add all of the URLs from which you want to perform silent authentication in the **Allowed Web Origins** field for your Application using the Auth0 Dashboard.
+
+## Poll with `checkSession()`
+
+<%= include('../../_includes/_checksession_polling') %>
+
+## Silent authentication with MFA
+
+In some scenarios, you may want to avoid prompting the user for MFA each time they log in from the same browser. To do this, set up a rule so that MFA occurs only once per session. This is useful when performing silent authentication (`prompt=none`) to renew short-lived Access Tokens in a SPA during the duration of a user's session without having to rely on setting `allowRememberBrowser` to `true`.
+
+```js
+function (user, context, callback) {
+ const completedMfa = !!context.authentication.methods.find(
+ (method) => method.name === 'mfa'
+ );
+
+ if (completedMfa) {
+ return callback(null, user, context);
+ }
+
+ context.multifactor = {
+ provider: 'any',
+ allowRememberBrowser: false
+ };
+
+ callback(null, user, context);
+}
+```
-### How to implement
+See [Change Authentication Request Frequency](/mfa/guides/customize-mfa-universal-login#change-authentication-request-frequency) for details.
-Implementation of token renewal will depend on the type of application and framework being used. Sample implementations for some of the common platforms can be found below:
+## Keep reading
-* [Plain JavaScript](/quickstart/spa/vanillajs/05-token-renewal)
-* [jQuery](/quickstart/spa/jquery/05-token-renewal)
-* [React](/quickstart/spa/react/05-token-renewal)
-* [Angular](/quickstart/spa/angular2/05-token-renewal)
-* [ASP.NET Core MVC](https://github.com/auth0-samples/auth0-aspnetcore-mvc-samples/tree/master/Samples/silent-auth)
+* [Refresh Token Rotation](/tokens/concepts/refresh-token-rotation)
+* [Configure Refresh Token Rotation](/tokens/guides/configure-refresh-token-rotation)
diff --git a/articles/api-auth/tutorials/using-resource-owner-password-from-server-side.md b/articles/api-auth/tutorials/using-resource-owner-password-from-server-side.md
index ba92776416..e6a60b46de 100644
--- a/articles/api-auth/tutorials/using-resource-owner-password-from-server-side.md
+++ b/articles/api-auth/tutorials/using-resource-owner-password-from-server-side.md
@@ -1,20 +1,28 @@
---
-title: Using resource owner password from the server side
-description: How to use Resource Owner Password Grant from the server side together with anomaly detection.
+description: Learn how to use Resource Owner Password Grant (ROPG) from the server side together with anomaly detection.
toc: true
+topics:
+ - api-authentication
+ - oidc
+ - resource-owner-password
+ - anomaly-detection
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
---
-# Using Resource Owner Password from Server side
+# Use Resource Owner Password Grant From the Server Side
-<%= include('../../_includes/_pipeline2') %>
+<%= include('../_includes/_ropg-warning') %>
-Server-side applications can use the [Resource Owner Password Grant](/api-auth/grant/password) to access an API. The flow typically involves prompting the user for username and password as credentials which your server will submit to Auth0 to get an Access Token. When using this flow from server side, some anomaly detection features might fail because of the particularities of this scenario. This document details how to use [Resource Owner Password Grant](/api-auth/grant/password) flow from server side preventing some common issues.
+Server-side applications can use the [Resource Owner Password Grant](/api-auth/grant/password) to access an API. The flow typically involves prompting the user for username and password as credentials which your server will submit to Auth0 to get an Access Token. When using this flow from server side, some anomaly detection features might fail because of the particularities of this scenario. This document details how to use [Resource Owner Password Grant](/api-auth/grant/password) flow from server side preventing some common issues.
## Prerequisites
-Before you continue, make sure to have [brute force protection](/anomaly-detection#brute-force-protection) enabled from your dashboard.
+Before you continue, make sure to have [brute force protection](/anomaly-detection/guides/enable-disable-brute-force-protection) enabled from your dashboard.
-## The flow
+## How it works
1. Your server prompts the user for credentials (such as username and password). This could be achieved in many different ways, for example via a browser UI or providing an API.
@@ -31,35 +39,48 @@ Brute-force protection relies on having the original user's IP. When calling the
To prevent this, you may send the end-user's IP address to Auth0 along with the credentials and configure the application to trust the provided IP. Because of security considerations, this configuration is only possible for Authenticated applications (such as those with authentication based on a client secret).
::: warning
-Warning! Authenticated applications must only be used from protected resources, typically server-side. Do not use them from native applications or SPAs, as they are not capable of storing secrets.
+Authenticated applications must only be used from protected resources, typically server-side. Do not use them from native applications or SPAs, as they are not capable of storing secrets.
:::
+### Configure the Auth0 Application to receive and trust the IP sent by your server
-### Configuring the Auth0 Application to receive and trust the IP sent by your server
+1. Navigate to your [dashboard](${manage_url}) and [configure a regular web application or machine-to-machine application](/applications).
-1. Navigate to your [dashboard](${manage_url}) and configure a regular web application or machine to machine application using this [tutorial](/applications#how-to-configure-an-application).
+2. Choose a __Token Endpoint Authentication Method__ other than `None` under the [Settings](/dashboard/reference/settings-application) section.
-2. Choose a __Token Endpoint Authentication Method__ other than `None` under the [Settings](/applications#application-settings) section.
+ 
-
+3. Scroll to the bottom and click _Show Advanced Settings_.
-::: warning
-Due to security considerations, the configuration stated on Step 3 will not be available for Non-Authenticated applications.
-:::
+ ::: warning
+ Due to security considerations, the configuration stated on Step 3 will not be available for Non-Authenticated applications.
+ :::
-3. Scroll to the bottom and click _Show Advanced Settings_.
+4. Enable __Trust Token Endpoint IP Header__ under the _OAuth_ tab to configure the application to trust the IP sent from your server.
+
+ 
+
+### Send the end-user IP from your server
+
+If your application is configured to send the `auth0-forwarded-for` header and it authenticates (sends `client_secret` in the request):
-4. Switch on __Trust Token Endpoint IP Header__ under the _OAuth_ tab to configure the application to trust the IP sent from your server.
+- Only the IP in the `auth0-forwarded-for` header is checked against the brute-force protection whitelist.
+- The corollary to the above is the proxy IP is ignored by brute-force protection. Don't add the proxy IP to the whitelist (if you did it would have no effect).
+- If specific clients that use the proxy should be whitelisted, add them to the whitelist and they will not be subject to brute-force protection.
-
+If the application is **not** configured to use the `auth0-forwarded-for` header *or* if it does not authenticate (send `client_secret` in the request):
-### Sending the end-user IP from your server
+- The originating IP of each request is checked against the brute-force protection whitelist.
+- Whitelisting the IP proxy exempts **all** traffic passing through the proxy from brute-force protection (this is probably not what you want).
-To send the end-user IP from your server, include a `auth0-forwarded-for` header with the value of the end-user IP address. If the IP is valid, Auth0 will use it as the source IP for brute-force protection. It is important to make sure the provided IP address really belongs to your end user.
+1. To send the end-user IP from your server, include a `auth0-forwarded-for` header with the value of the end-user IP address.
+
+ If the `auth0-forwarded-for` header is marked as trusted, as explained above, Auth0 will use it as the source IP for [brute-force protection](/anomaly-detection). It is important to make sure the provided IP address really belongs to your end user.
+
+2. When using the resource owner password grant from your webserver with brute-force protection enabled, specify a whitelist of IPs that will not be considered when triggering brute-force protection. Both the `auth0-forwarded-for` IP address and the IP address of the proxy server will be taken into account for IP address whitelists.
::: warning
-Warning! Trusting headers like the x-forwarded-for (or, in general, data from application) as source for the end-user IP can be a big risk. This should not be done unless you know you can trust that header, since it is easy to spoof and makes possible to bypass the anomaly-detection validation.
-
+Trusting headers like the `x-forwarded-for` (or, in general, data from application) as source for the end user IP can be a big risk. This should not be done unless you know you can trust that header, since it is easy to spoof and makes possible to bypass the anomaly detection validation.
:::
### Example
@@ -72,19 +93,18 @@ app.post('/api/auth', function(req, res, next) {
method: 'POST',
url: 'https://${account.namespace}/oauth/token',
headers: {
- 'content-type': 'application/json',
+ 'content-type': 'application/x-www-form-urlencoded',
'auth0-forwarded-for': req.ip // End user ip
},
- body: {
+ form: {
grant_type: 'password',
username: 'USERNAME',
password: 'PASSWORD',
- audience: 'API_IDENTIFIER',
+ audience: 'YOUR_API_IDENTIFIER',
scope: 'SCOPE',
client_id: '${account.clientId}',
client_secret: 'YOUR_CLIENT_SECRET' // Client is authenticated
- },
- json: true
+ }
};
request(options, function (error, response, body) {
@@ -94,3 +114,15 @@ app.post('/api/auth', function(req, res, next) {
});
});
```
+
+### Validate with logs
+
+If your settings are working correctly, you will see the following in the logs:
+
+```text
+type: sepft
+...
+ip:
+client_ip:
+...
+```
\ No newline at end of file
diff --git a/articles/api-auth/tutorials/verify-access-token.md b/articles/api-auth/tutorials/verify-access-token.md
deleted file mode 100644
index b67ea77669..0000000000
--- a/articles/api-auth/tutorials/verify-access-token.md
+++ /dev/null
@@ -1,154 +0,0 @@
----
-description: How an API can verify a bearer JWT Access Token
-toc: true
----
-# Verify Access Tokens for Custom APIs
-
-<%= include('../../_includes/_pipeline2') %>
-
-When a custom API receives a request with a bearer [Access Token](/tokens/access-token), the first thing to do is to validate the token. At Auth0, an Access Token used for a custom API is formatted as a [JSON Web Token](/jwt). Validating the token consists of a series of steps, and if any of these fails then the request **must** be rejected.
-
-This document lists all the validations that your API should perform:
-
-- Check that the JWT is well formed
-- Check the signature
-- Validate the standard claims
-- Check the Application permissions (scopes)
-
-::: note
-JWT.io provides a list of libraries that can do most of the work for you: parse the JWT, verify the signature and the claims.
-:::
-
-## Parse the JWT
-
-First, the API needs to parse the JSON Web Token (JWT) to make sure it's well formed. If this fails the token is considered invalid and the request must be rejected.
-
-A well formed JWT, consists of three strings separated by dots (.): the header, the payload and the signature. Typically it looks like the following:
-
-
-
-The header and the payload are Base64Url encoded. The signature is created using these two, a secret and the hashing algorithm being used (as specified in the header: HMAC, SHA256 or RSA).
-
-For details on the JWT structure refer to [What is the JSON Web Token structure?](/jwt#what-is-the-json-web-token-structure-).
-
-### How can I parse the JWT?
-
-In order to parse the JWT you can either manually implement all the checks as described in the specification [RFC 7519 > 7.2 Validating a JWT](https://tools.ietf.org/html/rfc7519#section-7.2), or use one of the libraries listed in the _Libraries for Token Signing/Verification_ section of [JWT.io](https://jwt.io/).
-
-For example, if your API is implemented with Node.js and you want to use the [node-jsonwebtoken library](https://github.com/auth0/node-jsonwebtoken), then you would call the [jwt.verify()](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback) method. If the parsing fails then the library will return a [JsonWebTokenError error](https://github.com/auth0/node-jsonwebtoken#jsonwebtokenerror) with the message `jwt malformed`.
-
-We should note here that many web frameworks (such as [ASP.NET Core](/quickstart/backend/aspnet-core-webapi) for example) have JWT middleware that handle the token validation. Most of the times this will be a better route to take, rather that resorting to use a third-party library, as the middleware typically integrates well with the framework's overall authentication mechanisms.
-
-### How can I visually inspect a token?
-
-A quick way to see what is inside a JWT is by using the [JWT.io](https://jwt.io/) website (alternatively, you can use the [JWT Debugger Chrome Extension](https://chrome.google.com/webstore/detail/jwt-debugger/ppmmlchacdbknfphdeafcbmklcghghmd?hl=en)). It has a handy debugger which allows you to quickly check that a JWT is well formed, and also inspect the values of the various claims.
-
-Just paste your token at the _Encoded_ text area and review the decoded results at the right.
-
-
-
-## Check the Signature Algorithm
-
-The API needs to check if the algorithm, as specified by the JWT header (property `alg`), matches the one expected by the API. If not, the token is considered invalid and the request must be rejected.
-
-In this case the mismatch might be due to mistake (it is common that the tokens are signed using the `HS256` signing algorithm, but your API is configured for `RS256`, or vice versa), but it could also be due to an attack, hence the request has to be rejected.
-
-### How can I check the signature algorithm?
-
-To check if the signature matches the API's expectations, you have to decode the JWT and retrieve the `alg` property of the JWT header.
-
-Alternatively, you can use one of the libraries listed in the _Libraries for Token Signing/Verification_ section of [JWT.io](https://jwt.io/).
-
-Following the Node.js example of the previous section, the [jwt.verify()](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback) method of the [node-jsonwebtoken library](https://github.com/auth0/node-jsonwebtoken), supports an `algorithms` argument, that contains a list of strings with the names of the allowed algorithms.
-
-## Verify the signature
-
-The API needs to verify the signature of each token.
-
-This is necessary to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
-
-Remember that the signature is created using the header and the payload of the JWT, a secret and the hashing algorithm being used (as specified in the header: HMAC, SHA256 or RSA). The way to verify it, depends on the hashing algorithm:
-
-- For `HS256`, the API's __Signing Secret__ is used. You can find this information at your [API's Settings](${manage_url}/#/apis). Note that the field is only displayed for APIs that use `HS256`.
-- For `RS256`, the tenant's [JSON Web Key Set (JWKS)](/jwks) is used. Your tenant's JWKS is `https://${account.namespace}/.well-known/jwks.json`.
-
-The most secure practice, and our recommendation, is to use `RS256`.
-
-### How can I verify the signature?
-
-To verify a token's signature, you can use one of the libraries available in [JWT.io](https://jwt.io/#libraries-io).
-
-Following the Node.js example of the previous section, the [jwt.verify()](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback) method supports a `secretOrPublicKey` argument. This should be populated with a string or buffer containing either the secret (for `HS256`), or the PEM encoded public key (for `RS256`).
-
-::: panel Where can I find my public key?
-Go to [Dashboard > Applications](${manage_url}/#/applications). Open the **Settings** of your application, scroll down and open **Advanced Settings**. Open the **Certificates** tab and you will find the Public Key in the **Signing Certificate** field.
-
-If you want to verify the signature of a token from one of your applications, we recommend getting it by parsing your tenant's [JSON Web Key Set (JWKS)](/jwks). Your tenant's JWKS is `https://${account.namespace}/.well-known/jwks.json`.
-
-For more info on **RS256** and **JWKS** see [Navigating RS256 and JWKS](https://auth0.com/blog/navigating-rs256-and-jwks/).
-:::
-
-If the verification fails you will get a `invalid signature` error.
-
-## Validate the Claims
-
-Once the API verifies the token's signature, the next step is to validate the standard claims of the token's payload. The following validations need to be made:
-
-- _Token expiration_: The current date/time _must_ be before the expiration date/time listed in the `exp` claim (which is a Unix timestamp). If not, the request must be rejected.
-- _Token issuer_: The `iss` claim denotes the issuer of the JWT. The value _must_ match the one configured in your API. For JWTs issued by Auth0, `iss` holds your Auth0 domain with a `https://` prefix and a `/` suffix: `https://${account.namespace}/`. If you are using the [custom domains](/custom-domains) feature, the value will instead be in the following format: `https:///`.
-- _Token audience_: The `aud` claim identifies the recipients that the JWT is intended for. For JWTs issued by Auth0, `aud` holds the unique identifier of the target API (field __Identifier__ at your [API's Settings](${manage_url}/#/apis)). If the API is not the intended audience of the JWT, it _must_ reject the request.
-
-::: panel Token issuance
-Auth0 issues tokens with the **iss** claim of whichever domain you used with the request. Custom domain users might use either, their custom domain, or their Auth0 domain. For example, if you used **https://northwind.auth0.com/authorize...** to obtain an Access Token, the **iss** claim of the token you receive will be **https://northwind.auth0.com/**. If you used your custom domain **https://login.northwind.com/authorize...**, the **iss** claim value will be **https://login.northwind.com/**.
-
-If you get an Access Token for the [Management API](/api/management/v2) using an authorization flow with your custom domain, you **must** call the Management API using the custom domain (your token will be considered invalid otherwise).
-:::
-
-### How can I validate the claims?
-
-To validate the claims, you have to decode the JWT, retrieve the claims (`exp`, `iss`, `aud`) and validate their values.
-
-The easiest way however, is to use one of the libraries listed in the _Libraries for Token Signing/Verification_ section of [JWT.io](https://jwt.io/). Note that not all libraries validate all the claims. In [JWT.io](https://jwt.io/) you can see which validations each library supports (look for the green check marks).
-
-Following the Node.js example, the [jwt.verify()](https://github.com/auth0/node-jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback) method of the [node-jsonwebtoken library](https://github.com/auth0/node-jsonwebtoken), validates these claims, depending on the input arguments:
-
-- `audience`: set `aud` to the __Identifier__ of the API
-- `issuer`: string or array of strings of valid values for the `iss` field
-- `ignoreExpiration`: set to `false` to validate the expiration of the token
-
-## Check the Permissions
-
-By now you have verified that the JWT is valid. The last step is to verify that the application has the permissions required to access the protected resources.
-
-To do so, you need to check the [scopes](/scopes) of the decoded JWT. This claim is part of the payload and it is a space-separated list of strings.
-
-### How can I check the permissions?
-
-To check the permissions granted to the application, you need to check the contents of the `scope`.
-
-For example, a user management API might provide three endpoints to read, create or delete a user record: `/create`, `/read` and `/delete`. We have configured this API, so each endpoint requires a specific permission (or scope):
-
-- The `read:users` scope provides access to the `/read` endpoint.
-- The `create:users` scope provides access to the `/create` endpoint.
-- The `delete:users` scope provides access to the `/delete` endpoint.
-
-If a request requests to access the `/create` endpoint, but the `scope` claim does NOT include the value `create:users`, then the API should reject the request with `403 Forbidden`.
-
-You can see how to do this, for a simple timesheets API in Node.js, in this document: [Check the Application permissions](/architecture-scenarios/application/server-api/api-implementation-nodejs#check-the-application-permissions).
-
-## Sample Implementation
-
-You can find a sample API implementation, in Node.js, in [Server Application + API: Node.js Implementation for the API](/architecture-scenarios/application/server-api/api-implementation-nodejs).
-
-This document is part the [Server + API Architecture Scenario](/architecture-scenarios/application/server-api), an implementation of a Client Credentials grant for a hypothetical scenario. For more information on the complete solution refer to [Server + API Architecture Scenario](/architecture-scenarios/application/server-api).
-
-
-## Read more
-
-- [RFC 7519 - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519)
-- [JSON Web Tokens (JWT) in Auth0](/jwt)
-- [APIs in Auth0](/apis)
-- [Why you should always use Access Tokens to secure an API](/api-auth/why-use-access-tokens-to-secure-apis)
-- [Tokens used by Auth0](/tokens)
-- [Server Application + API: Node.js Implementation for the API](/architecture-scenarios/application/server-api/api-implementation-nodejs#check-the-application-permissions)
-- [How to implement API authentication and authorization scenarios](/api-auth)
diff --git a/articles/api-auth/user-consent.md b/articles/api-auth/user-consent.md
index 7d6e2aa839..75c4329390 100644
--- a/articles/api-auth/user-consent.md
+++ b/articles/api-auth/user-consent.md
@@ -1,38 +1,29 @@
---
-title: User consent and third-party applications
+description: Learn how to decouple APIs from applications that consume them and define third-party apps that you don't control or may not trust.
+topics:
+ - api-authentication
+ - oidc
+ - user-consent
+contentType: how-to
+useCase:
+ - secure-api
+ - call-api
---
# User Consent and Third-Party Applications
-<%= include('../_includes/_pipeline2') %>
+The [OIDC-conformant authentication pipeline](/api-auth/tutorials/adoption) supports defining [resource servers (such as APIs) as entities separate from applications](/api-auth/tutorials/adoption/api-tokens). This lets you decouple APIs from the applications that consume them, and also lets you define third-party applications that you might not control or even fully trust.
-The [OIDC-conformant authentication pipeline](/api-auth/tutorials/adoption) supports defining [resource servers (such as APIs) as entities separate from applications](/api-auth/tutorials/adoption/api-tokens).
-This lets you decouple APIs from the applications that consume them, and also lets you define third-party applications that you might not control or even fully trust.
+All applications created from the [Dashboard](${manage_url}/#/applications) are assumed to be first-party by default.
-## Types of applications
-
-All Auth0 applications are either first-party or third-party.
-
-**First-party** applications are those controlled by the same organization or person that owns the Auth0 domain.
-For example, suppose you wanted to access the Contoso API; in this case, there would likely be a first-party application used for logging in at contoso.com.
-
-**Third-party** applications are controlled by different people or organizations who most likely should not have administrative access to your Auth0 domain.
-They enable external parties or partners to access protected resources at your API in a secure way.
-A practical application of third-party applications is the creation of "developer centers", which allow users to obtain credentials in order to integrate their applications with your API.
-Similar functionality is provided by well-known APIs such as Facebook, Twitter, GitHub, and many others.
-
-## Creating a third-party application
-
-All applications created from the [management dashboard](${manage_url}/#/applications) are assumed to be first-party by default.
-
-At the time of writing, third-party applications cannot be created from the management dashboard.
-They must be created through the management API, by setting `is_first_party: false`.
+Third-party applications cannot be created from the Dashboard. They must be created through the Management API, by setting `is_first_party: false`.
All applications created through [Dynamic Client Registration](/api-auth/dynamic-client-registration) will be third-party.
## Consent dialog
If a user is authenticating through a third-party application and is requesting authorization to access the user's information or perform some action at an API on their behalf, they will see a consent dialog.
+
For example:
-If the user chooses to allow the application, this will create a user grant which represents this user's consent to this combination of application, resource server and scopes.
+If the user allows the application, this creates a *user grant* which represents the user's consent to this combination of application, resource server, and scopes.
+
+The application then receives a successful authentication response from Auth0 as usual. Once consent has been given, the user won't see the consent dialog during subsequent logins until consent is revoked explicitly.
-The application will then receive a successful authentication response from Auth0 as usual.
+## Scope descriptions
-Once consent has been given, the user will no longer see the consent dialog on subsequent logins.
+By default, the consent page will use the scopes' names to prompt for the user's consent. As shown below, you should define scopes using the **action:resource_name** format.
-## Handling rejected permissions
+
+
+The consent page groups scopes for the same resource and displays all actions for that resource in a single line. For example, the configuration above would result in **Posts: read and write your posts**.
+
+If you would like to display the **Description** field instead, you can do so by setting the tenant's **use_scope_descriptions_for_consent** to **true**. This will affect consent prompts for all of the APIs on that tenant.
+
+To set the **use_scope_descriptions_for_consent** flag, you will need to make the appropriate call to the API:
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/tenants/settings",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer API2_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"flags\": { \"use_scope_descriptions_for_consent\": true } }"
+ }
+}
+```
+
+## Handle rejected permissions
If a user decides to reject consent to the application, they will be redirected to the `redirect_uri` specified in the request with an `access_denied` error:
@@ -73,7 +90,7 @@ Location: https://fabrikam.com/contoso_social#
&state=...
```
-## Skipping consent for first-party applications
+## Skip consent for first-party applications
Only first-party applications can skip the consent dialog, assuming the resource server they are trying to access on behalf of the user has the "Allow Skipping User Consent" option enabled.
@@ -84,12 +101,12 @@ Note that this option only allows __verifiable__ first-party applications to ski
127.0.0.1 myapp.example
```
-Once you do this, remember to update your application configuration URLs, such as the **Allowed Callback URLs** (found in [Dashboard > Applications > Settings](${manage_url}/#/applications/${account.clientId}/settings)), and the callback URL you configured in your application, to match the updated domain-mapping.
+Similarly, you **cannot** skip consent (even for first-party applications) if `localhost` appears in any domain in the **Allowed Callback URLs** setting (found in [Dashboard > Applications > Settings](${manage_url}/#/applications/${account.clientId}/settings)). Make sure to update **Allowed Callback URLs**, and the callback URL you configured in your application, to match the updated domain-mapping.
:::
Since third-party applications are assumed to be untrusted, they are not able to skip consent dialogs.
-## Revoking Consent
+## Revoke Consent
If a user has provided consent, but you would like to revoke it, you can do so via [Dashboard > Users](${manage_url}/#/users). Select the user in which you are interested, and switch over to the **Authorized Applications** tab.
@@ -100,11 +117,18 @@ Click **Revoke** next to the appropriate application.
When performing a [Resource Owner Password Credentials exchange](/api-auth/grant/password), there is no consent dialog involved.
During a password exchange, the user provides their password to the application directly, which is equivalent to granting the application full access to the user's account.
-### Forcing users to provide consent
+### Force users to provide consent
When redirecting to /authorize, the `prompt=consent` parameter will force users to provide consent, even if they have an existing user grant for that application and requested scopes.
-### Customizing the consent dialog
+### Customize the consent dialog
+
+The consent dialog UI cannot be customized or set to a custom domain.
+
+## Keep reading
-As of today the consent dialog UI cannot be customized or set to a custom domain.
-We plan to implement this in future releases.
+* [First-Party and Third-Party Applications](/applications/concepts/app-types-first-third-party)
+* [View Application Ownership](/api/management/guides/applications/view-ownership)
+* [Confidential and Public Applications](/applications/concepts/app-types-confidential-public)
+* [Enable Third-Party Applications](/applications/guides/enable-third-party-apps)
+* [Auth0 Grant Types Mapping](/applications/reference/grant-types-auth0-mapping)
diff --git a/articles/api-auth/which-oauth-flow-to-use.md b/articles/api-auth/which-oauth-flow-to-use.md
index a89e2c4447..3c2fe7f418 100644
--- a/articles/api-auth/which-oauth-flow-to-use.md
+++ b/articles/api-auth/which-oauth-flow-to-use.md
@@ -1,55 +1,69 @@
---
-title: Which OAuth 2.0 flow should I use?
+title: Which OAuth 2.0 Flow Should I Use?
toc: true
-description: Helps the user identify the proper OAuth 2.0 grant for each use case.
+description: Learn how to identify the proper OAuth 2.0 grant for your use case.
+topics:
+ - api-authentication
+ - oidc
+ - application-grants
+ - flows
+contentType:
+ - concept
+useCase:
+ - secure-api
+ - call-api
---
-# Which OAuth 2.0 flow should I use?
+# Which OAuth 2.0 Flow Should I Use?
-<%= include('../_includes/_pipeline2') %>
+[OAuth 2.0](https://tools.ietf.org/html/rfc6749) supports several different **grants**. Grants are ways of retrieving an Access Token. Deciding which one is suited for your case depends mostly on your Client's type, but other parameters weigh in as well, like the level of trust for the Client, or the experience you want your users to have.
-OAuth 2.0 supports several different **grants**. By grants we mean ways of retrieving an Access Token. Deciding which one is suited for your case depends mostly on your Application's type, but other parameters weigh in as well, like the level of trust for the Application, or the experience you want your users to have.
+## OAuth 2.0 terminology
-Follow this flow to identify the grant that best matches your case.
-
-
-
-::: panel Quick refresher - OAuth 2.0 terminology
- **Resource Owner**: the entity that can grant access to a protected resource. Typically this is the end-user.
-- **Application**: an application requesting access to a protected resource on behalf of the Resource Owner.
+- **Client**: an application requesting access to a protected resource on behalf of the Resource Owner.
- **Resource Server**: the server hosting the protected resources. This is the API you want to access.
-- **Authorization Server**: the server that authenticates the Resource Owner, and issues Access Tokens after getting proper authorization. In this case, Auth0.
-- **User Agent**: the agent used by the Resource Owner to interact with the Application, for example a browser or a native application.
-:::
+- **Authorization Server**: the server that authenticates the Resource Owner and issues Access Tokens after getting proper authorization. In this case, Auth0.
+- **User Agent**: the agent used by the Resource Owner to interact with the Client, for example a browser or a native application.
+
+## Is the Client the Resource Owner?
+
+The first decision point is about whether the party that requires access to resources is a machine. In the case of machine-to-machine authorization, the Client is also the Resource Owner, so no end-user authorization is needed. An example is a cron job that uses an API to import information to a database. In this example, the cron job is the Client and the Resource Owner since it holds the Client ID and Client Secret and uses them to get an Access Token from the Authorization Server.
+
+If this case matches your needs, then for more information on how this flow works and how to implement it, refer to [Client Credentials Flow (Client Credentials Grant)](/flows/concepts/client-credentials).
+
+## Is the Client a web app executing on the server?
+
+If the Client is a regular web app executing on a server, then the **Authorization Code Flow (Authorization Code grant)** is the flow you should use. Using this the Client can retrieve an Access Token and, optionally, a Refresh Token. It's considered the safest choice since the Access Token is passed directly to the web server hosting the Client, without going through the user's web browser and risk exposure.
+
+If this case matches your needs, then for more information on how this flow works and how to implement it, refer to [Authorization Code Flow](/flows/concepts/auth-code).
-## Is the Application the Resource Owner?
+## Is the Client absolutely trusted with user credentials?
-The first decision point is about whether the party that requires access to resources is a machine. In this case of machine to machine authorization, the Application is also the Resource Owner. No end-user authorization is needed in this case. An example is a cron job that uses an API to import information to a database. In this example the cron job is the Application and the Resource Owner since it holds the Client ID and Client Secret and uses them to get an Access Token from the Authorization Server.
+This decision point may result in the **Resource Owner Password Credentials Grant**. In this flow, the end-user is asked to fill in credentials (username/password), typically using an interactive form. This information is sent to the backend and from there to Auth0. It is therefore imperative that the Client is absolutely trusted with this information.
-If this case matches your needs, then for more information on how this flow works and how to implement it refer to [Calling APIs from a service](/api-auth/grant/client-credentials).
+This grant should **only** be used when redirect-based flows (like the [Authorization Code Flow](/flows/concepts/auth-code)) are not possible. If this is your case, then for more information on how this flow works and how to implement it, refer to [Call APIs from Highly Trusted Applications](/api-auth/grant/password).
-## Is the Application a web app executing on the server?
+## Is the Client a Single Page App?
-If the Application is a regular web app executing on a server then the **Authorization Code Grant** is the flow you should use. Using this the Application can retrieve an Access Token and, optionally, a Refresh Token. It's considered the safest choice since the Access Token is passed directly to the web server hosting the Application, without going through the user's web browser and risk exposure.
+If the Client is a Single Page App, an application running in a browser using a scripting language like JavaScript, there are two grant options: the **Authorization Code Grant using Proof Key for Code Exchange (PKCE)** and the **Implicit Grant**. For most cases, we recommend using the Authorization Code Grant with PKCE.
-If this case matches your needs, then for more information on how this flow works and how to implement it refer to [Calling APIs from server-side web apps](/api-auth/grant/authorization-code).
+### Authorization Code Grant with PKCE
-## Is the Application absolutely trusted with user credentials?
+This grant adds the concept of a `code_verifier` to the Authorization Code Grant. When the Client asks for an **Authorization Code** it generates a `code_verifier` and its transformed value called `code_challenge`. The `code_challenge` and a `code_challenge_method` are sent along with the request. When the Client wants to exchange the Authorization Code for an Access Token, it also sends along the `code_verifier`. The Authorization Server transforms this and if it matches the originally sent `code_challenge`, it returns an Access Token.
-This decision point may result to suggesting the **Resource Owner Password Credentials Grant**. In this flow the end-user is asked to fill in credentials (username/password) typically using an interactive form. This information is sent to the backend and from there to Auth0. It is therefore imperative that the Application is absolutely trusted with this information.
+The [Auth0 Single Page App SDK](/libraries/auth0-spa-js) provides high-level API for implementing Authorization Code Grant with PKCE in single page applications.
-This grant should **only** be used when redirect-based flows (like the [Authorization Code Grant](/api-auth/grant/authorization-code)) are not possible. If this is your case, then for more information on how this flow works and how to implement it refer to [Call APIs from Highly Trusted Applications](/api-auth/grant/password).
+For more information on how this flow works and how to implement it, refer to [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce).
-## Is the Application a native app or a SPA?
+### Implicit Grant
-If the Application is a Single Page Application (meaning an application running in a browser using a scripting language such as Javascript) then the **Implicit Grant** should be used. In this case, instead of getting an authorization code that needs to be exchanged for an Access Token, the Application retrieves directly an Access Token. On the plus side, this is more efficient since it reduces the number of round trips required to get an Access Token. However, a security consideration is that the Access Token is exposed on the client side. Also, it should be noted that **Implicit Grant** does not return a Refresh Token because the browser cannot keep it private (read the __SPAs and Refresh Tokens__ panel for a workaround).
+In this case, instead of getting an authorization code that needs to be exchanged for an Access Token, the Application directly retrieves an Access Token. On the plus side, this is more efficient since it reduces the number of round trips required to get an Access Token. However, a security consideration is that **the Access Token is exposed on the client side**. Also, note that this flow does not return a Refresh Token because the browser cannot keep it private.
-For more information on how this flow works and how to implement it, refer to [Call APIs from client-side web apps](/api-auth/grant/implicit).
+For more information on how this flow works and how to implement it, refer to [Implicit Flow](/flows/concepts/implicit).
-::: panel SPAs and Refresh Tokens
-While SPAs cannot use [Refresh Tokens](/tokens/refresh-token), they can take advantage of other mechanics that provide the same function. A workaround to improve user experience is to use `prompt=none` when you invoke [the /authorize endpoint](/api/authentication#implicit-grant). This will not display the login dialog or the consent dialog. For more information on this, refer to [Silent Authentication](/api-auth/tutorials/silent-authentication). In addition to that if you call `/authorize` from a hidden iframe and extract the new [Access Token](/tokens/access-token) from the parent frame, then the user will not see the redirects happening.
-:::
+## Is the Client a Native/Mobile App?
-If the Application is a native app then the **Authorization Code Grant using Proof Key for Code Exchange** should be used. This grant adds the concept of a `code_verifier` to the Authorization Code Grant. When at first the application asks for an **Authorization Code** it generates a `code_verifier` and its transformed value called `code_challenge`. The `code_challenge` is sent along with the request. A `code_challenge_method` is also sent. Afterwards, when the application wants to exchange the Authorization Code for an Access Token, it also sends along the `code_verifier`. The Authorization Server transforms this and if it matches the originally sent `code challenge` it returns an Access Token.
+If the Application is a native app, then the **Authorization Code Flow with PKCE (Authorization Code Grant using Proof Key for Code Exchange)** should be used.
-For more information on how this flow works and how to implement it, refer to [Calling APIs from Mobile Apps](/api-auth/grant/authorization-code-pkce).
+For more information on how this flow works and how to implement it, refer to [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce).
diff --git a/articles/api-auth/why-use-access-tokens-to-secure-apis.md b/articles/api-auth/why-use-access-tokens-to-secure-apis.md
deleted file mode 100644
index 67de3e521d..0000000000
--- a/articles/api-auth/why-use-access-tokens-to-secure-apis.md
+++ /dev/null
@@ -1,106 +0,0 @@
----
-title: Why you should always use Access Tokens to secure an API
-description: Explains the differences between Access Token and ID Token and why the latter should never be used to secure an API.
----
-# Why you should always use Access Tokens to secure an API
-
-<%= include('../_includes/_pipeline2') %>
-
-There is much confusion on the Web about the differences between the OpenID Connect and OAuth 2.0 specifications, and their respective tokens. As a result many developers publish insecure applications, compromising their users security. The contradicting implementations between identity providers do not help either.
-
-This article is an attempt to clear what is what and explain why you should always use an [Access Token](/tokens/access-token) to secure an API, and never an [ID Token](/tokens/id-token).
-
-## Two complementary specifications
-
-OAuth 2.0 is used to __grant authorization__. It enables you to authorize the Web App A to access your information from Web App B, without sharing your credentials. It was built with _only_ authorization in mind and doesn't include any authentication mechanisms (in other words, it doesn't give the Authorization Server any way of verifying who the user is).
-
-OpenID Connect builds on OAuth 2.0. It enables you, the user, to verify your identity and give some basic profile information, without sharing your credentials.
-
-An example is a to-do application which lets you log in using your Google account and can push your to-do items, as calendar entries, to your Google Calendar. The part where you authenticate your identity is implemented via OpenID Connect, while the part where you authorize the to-do application to modify your calendar by adding entries, is implemented via OAuth 2.0.
-
-::: note
- OpenID Connect is about who someone is. OAuth 2.0 is about what they are allowed to do.
-:::
-
-You may have noticed the _"without sharing your credentials"_ part, in our definitions of the two specifications earlier. What you do share in both cases are **tokens**.
-
-OpenID Connect issues an identity token, known as an `id_token`, while OAuth 2.0 issues an `access_token`.
-
-## How to use each token
-
-The `id_token` is a [JWT](/jwt) and is meant for the application only. In the example we used earlier, when you authenticate using Google, an `id_token` is sent from Google to the to-do application, that says who you are. The to-do application can parse [the token's contents](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) and use this information, like your name and your profile picture, to customize the user experience.
-
-::: warning
-You must never use the info in an `id_token` unless you have validated it! For more information refer to: [How to validate an ID Token](/tokens/id-token#validate-an-id-token). For a list of libraries you can use to verify a JWT refer to [jwt.io](https://jwt.io/).
-:::
-
-The `access_token` can be any type of token (not necessarily a JWT) and is meant for the API. Its purpose is to inform the API that the bearer of this token has been authorized to access the API and perform specific actions (as specified by the `scope` that has been granted). In the example we used earlier, after you authenticate, and provide your consent that the to-do application can have read/write access to your calendar, an `access_token` is sent from Google to the to-do application. Each time the to-do application wants to access your Google Calendar it will make a request to the Google Calendar API, using this `access_token` in an HTTP `Authorization` header.
-
-::: note
- Access Tokens should be treated as opaque strings by applications. They are only meant for the API. Your application should not attempt to decode them or depend on a particular access_token format.
-:::
-
-## How NOT to use each token
-
-Now that we've seen what these tokens can be used for, let's see what they cannot be used for.
-
-- __An `access_token` cannot be used for authentication__. It holds no authenticating information about the user (in fact, the only identifying information about the user is their ID, located in the `sub` claim). It cannot tell us if the user has authenticated and when.
-
-- __An `id_token` cannot be used for API access__. Each token contains information on the intended audience (recipient). According to the OpenID Connect specification, the audience (claim `aud`) of each `id_token` must be the `client_id` of the application making the authentication request. If it isn't you shouldn't trust the token. An API, on the other hand, expects a token with the audience set to the API's unique identifier. So unless you are in control of both the application and the API, sending an `id_token` to an API will not work. Furthermore, the `id_token` is signed with a secret that is known to the application (since it is issued to a particular application). This means that if an API were to accept such token, it would have no way of knowing if the application has modified the token (to add more scopes) and then signed it again.
-
-## Compare Tokens
-
-To better understand what we just read, let's look at the contents of example tokens.
-
-The (decoded) contents of an `id_token` look like the following:
-
-```json
-{
- "iss": "http://${account.namespace}/",
- "sub": "auth0|123456",
- "aud": "${account.clientId}",
- "exp": 1311281970,
- "iat": 1311280970,
- "name": "Jane Doe",
- "given_name": "Jane",
- "family_name": "Doe",
- "gender": "female",
- "birthdate": "0000-10-31",
- "email": "janedoe@example.com",
- "picture": "http://example.com/janedoe/me.jpg"
-}
-```
-
-This token is meant for __authenticating the user to the application__. Note that the audience (`aud` claim) of the token is set to the application's identifier, which means that only this specific application should consume this token.
-
-For comparison, let's look at the contents of an `access_token`:
-
-```json
-{
- "iss": "https://${account.namespace}/",
- "sub": "auth0|123456",
- "aud": [
- "my-api-identifier",
- "https://${account.namespace}/userinfo"
- ],
- "azp": "${account.clientId}",
- "exp": 1489179954,
- "iat": 1489143954,
- "scope": "openid profile email address phone read:appointments email"
-}
-```
-
-This token is meant for __authorizing the user to the API__. As such, it is completely opaque to applications, meaning that an application should not care about the contents of this token, decode it or depend on a particular token format. Note that the token does not contain any information about the user itself besides their ID (`sub` claim), it only contains authorization information about which actions the application is allowed to perform at the API (`scope` claim).
-
-Since in many cases it is desirable to retrieve additional user information at the API, this token is also valid for calling the `/userinfo` API, which will return the user's profile information. So the intented audience (`aud` claim) of the token is either the API (`my-api-identifier`) or the `/userinfo` endpoint (`https://${account.namespace}/userinfo`).
-
-## Keep reading
-
-::: next-steps
-* [The problem with OAuth for Authentication](http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html)
-* [User Authentication with OAuth 2.0](https://oauth.net/articles/authentication/)
-* [OAuth 2.0 Overview](/protocols/oauth2)
-* [OpenID Connect Overview](/protocols/oidc)
-* [Obtaining and Using Access Tokens](/tokens/access-token)
-* [Obtaining and Using ID Tokens](/tokens/id-token)
-:::
diff --git a/articles/api/authentication/_application-reg.md b/articles/api/authentication/_application-reg.md
index 3ef1f90f27..21471c3821 100644
--- a/articles/api/authentication/_application-reg.md
+++ b/articles/api/authentication/_application-reg.md
@@ -39,7 +39,7 @@ curl --request POST \
"link": "#dynamic-application-client-registration"
}) %>
-With a name and the necessary callback URLs, you can dynamically register a client with Auth0. No token is needed for this request.
+With a name and the necessary callback URL, you can dynamically register a client with Auth0. No token is needed for this request.
### Request Parameters
@@ -47,4 +47,4 @@ With a name and the necessary callback URLs, you can dynamically register a clie
|:-----------------|:------------|
| `client_name` | The name of the Dynamic Client to be created. It is recommended to provide a value but if it is omitted, the default name "My App" will be used. |
| `redirect_uris` Required | An array of URLs that Auth0 will deem valid to call at the end of an Authentication flow. |
-| `token_endpoint_auth_method` | Default value is `client_secret_post`, but it can also be `none`. |
+| `token_endpoint_auth_method` | Default value is `client_secret_post`. Use `token_endpoint_auth_method: none` in the request payload if creating a SPA.|
diff --git a/articles/api/authentication/_change-password.md b/articles/api/authentication/_change-password.md
index 34d23d69e3..00e44b2854 100644
--- a/articles/api/authentication/_change-password.md
+++ b/articles/api/authentication/_change-password.md
@@ -1,13 +1,13 @@
# Change Password
-
+
```http
POST https://${account.namespace}/dbconnections/change_password
Content-Type: application/json
{
"client_id": "${account.clientId}",
"email": "EMAIL",
- "password": "",
"connection": "CONNECTION",
+ "organization": "ORGANIZATION_ID"
}
```
@@ -15,7 +15,7 @@ Content-Type: application/json
curl --request POST \
--url https://${account.namespace}/dbconnections/change_password \
--header 'content-type: application/json' \
- --data '{"client_id": "${account.clientId}","email": "EMAIL", "password": "", "connection": "CONNECTION"}'
+ --data '{"client_id": "${account.clientId}","email": "EMAIL", "connection": "CONNECTION", "organization": "ORGANIZATION_ID"}'
```
```javascript
@@ -29,7 +29,8 @@ curl --request POST \
webAuth.changePassword({
connection: 'CONNECTION',
- email: 'EMAIL'
+ email: 'EMAIL',
+ organization: 'ORGANIZATION_ID'
}, function (err, resp) {
if(err){
console.log(err.message);
@@ -53,40 +54,34 @@ curl --request POST \
"We've just sent you an email to reset your password."
```
-Given a user's `email` address and a `connection`, Auth0 will send a change password email.
+Send a change password email to the user's provided email address and `connection`.
+
+Optionally, you may provide an Organization ID to support Organization-specific variables in [customized email templates](/customize/email/email-templates#common-variables) and to include the `organization_id` and `organization_name` parameters in the **Redirect To** URL.
-This endpoint only works for database connections.
+Note: This endpoint only works for database connections.
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `client_id` Required | The `client_id` of your client. |
+| `client_id` | The `client_id` of your client. |
| `email` Required | The user's email address. |
-| `password ` | The new password. See the next paragraph for the case when a password can be set. |
| `connection` Required | The name of the database connection configured to your client. |
-
-
-### Test with Postman
-
-<%= include('../../_includes/_test-with-postman') %>
+| `organization` | The `organization_id` of the Organization associated with the user. |
### Remarks
-- If you are using Lock version 9 and above, **do not set the password field** or you will receive a *password is not allowed* error. You can only set the password if you are using Lock version 8.
-- If a password is provided, when the user clicks on the confirm password change link, the new password specified in this POST will be set for this user.
-- If a password is NOT provided, when the user clicks on the password change link they will be redirected to a page asking them for a new password.
-- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
+- When the user clicks on the password change link they will be redirected to a page asking them for a new password.
- This endpoint will return three HTTP Response Headers, that provide relevant data on its rate limits:
* `X-RateLimit-Limit`: Number of requests allowed per minute.
* `X-RateLimit-Remaining`: Number of requests available. Each new request reduces this number by 1. For each minute that passes, requests are added back, so this number increases by 1 each time.
* `X-RateLimit-Reset`: Remaining time until the rate limit (`X-RateLimit-Limit`) resets. The value is in [UTC epoch seconds](https://en.wikipedia.org/wiki/Unix_time).
-### More Information
+### Learn More
- [Changing a User's Password](/connections/database/password-change)
- [Password Strength in Auth0 Database Connections](/connections/database/password-strength)
- [Password Options in Auth0 Database Connections](/connections/database/password-options)
-- [Auth0 API Rate Limit Policy](/policies/rate-limits)
+- [Auth0 API Rate Limit Policy](/troubleshoot/customer-support/operational-policies/rate-limit-policy/rate-limit-configurations)
diff --git a/articles/api/authentication/_impersonation.md b/articles/api/authentication/_impersonation.md
deleted file mode 100644
index 66659ae9d1..0000000000
--- a/articles/api/authentication/_impersonation.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# Impersonation
-
-```http
-POST https://${account.namespace}/users/{user_id}/impersonate
-Content-Type: application/json
-Authorization: 'Bearer {ACCESS_TOKEN}'
-{
- protocol: "PROTOCOL",
- impersonator_id: "IMPERSONATOR_ID",
- client_id: "${account.clientId}",
- additionalParameters: [
- "response_type": "code",
- "state": "STATE"
- ]
-}
-```
-
-```shell
-curl --request POST \
- --url 'https://${account.namespace}/users/{user_id}/impersonate' \
- --header 'Authorization: Bearer {ACCESS_TOKEN}' \
- --header 'content-type: application/x-www-form-urlencoded; charset=UTF-8' \
- --data '{"protocol":"PROTOCOL", "impersonator_id":"IMPERSONATOR_ID", "client_id":"${account.clientId}", "additionalParameters": {"response_type": "code", "state": "STATE"}}'
-```
-
-```javascript
-var url = 'https://' + ${account.namespace} + '/users/' + localStorage.getItem('user_id') + '/impersonate';
-var params = 'protocol=PROTOCOL&impersonator_id=IMPERSONATOR_ID&client_id=${account.clientId}';
-
-var xhr = new XMLHttpRequest();
-
-xhr.open('POST', url);
-xhr.setRequestHeader('Content-Type', 'application/json');
-xhr.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('access_token'));
-
-xhr.onload = function() {
- if (xhr.status == 200) {
- fetchProfile();
- } else {
- alert("Request failed: " + xhr.statusText);
- }
-};
-
-xhr.send(params);
-```
-
-> RESPONSE SAMPLE:
-
-```text
-https:/YOUR_DOMAIN/users/IMPERSONATOR_ID/impersonate?&bewit=WFh0MUtm...
-```
-
-<% var path = '/users/{user_id}/impersonate'; %>
-<%=
-include('../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": path,
- "link": "#impersonation"
-}) %>
-
-<%= include('../../_includes/_deprecate-impersonation.md') %>
-
-Use this endpoint to obtain an impersonation URL to login as another user. Useful for troubleshooting.
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `protocol` Required | The protocol to use against the identity provider: `oauth2`, `samlp`, `wsfed`, `wsfed-rms`. |
-| `impersonator_id` Required | The `user_id` of the impersonator. |
-| `client_id` Required | The `client_id` of the client that is generating the impersonation link.|
-| `additionalParameters` | This is a JSON object. You can use this to set additional parameters, like `response_type`, `scope` and `state`. |
-
-### Remarks
-
-- This endpoint can only be used with **Global Client** credentials.
-
-- To distinguish between real logins and impersonation logins, the profile of the impersonated user will contain additional impersonated and impersonator properties. For example: `"impersonated": true, "impersonator": {"user_id": "auth0|...", "email": "admin@example.com"}`.
-
-- For a regular web app, you should set the `additionalParameters`: set the `response_type` to be `code`, the `callback_url` to be the callback url to which Auth0 will redirect with the authorization code, and the `scope` to be the JWT claims that you want included in the JWT.
-
-
-### More Information
-
-- [Impersonation](/user-profile/user-impersonation)
diff --git a/articles/api/authentication/_introduction.md b/articles/api/authentication/_introduction.md
index fac162fb6c..0df041af98 100644
--- a/articles/api/authentication/_introduction.md
+++ b/articles/api/authentication/_introduction.md
@@ -2,7 +2,7 @@
The Authentication API enables you to manage all aspects of user identity when you use Auth0. It offers endpoints so your users can log in, sign up, log out, access APIs, and more.
-The API supports various identity protocols, like [OpenID Connect](/protocols/oidc), [OAuth 2.0](/protocols/oauth2), and [SAML](/protocols/saml).
+The API supports various identity protocols, like [OpenID Connect](/protocols/oidc), [OAuth 2.0](/protocols/oauth2), [FAPI](/secure/highly-regulated-identity#advanced-security-with-openid-connect-fapi-) and [SAML](/protocols/saml).
:::note
This API is designed for people who feel comfortable integrating with RESTful APIs. If you prefer a more guided approach check out our [Quickstarts](/quickstarts) or our [Libraries](/libraries).
@@ -14,24 +14,49 @@ The Authentication API is served over HTTPS. All URLs referenced in the document
## Authentication methods
-There are three ways to authenticate with this API:
-- with an OAuth2 Access Token in the `Authorization` request header field (which uses the `Bearer` authentication scheme to transmit the Access Token)
-- with your Client ID and Client Secret credentials
-- only with your Client ID
+You have five options for authenticating with this API:
+- OAuth2 Access Token
+- Client ID and Client Assertion (confidential applications)
+- Client ID and Client Secret (confidential applications)
+- Client ID (public applications)
+- mTLS Authentication (confidential applications)
-Each endpoint supports only one option.
+### OAuth2 Access Token
-### OAuth2 token
+Send a valid Access Token in the `Authorization` header, using the `Bearer` authentication scheme.
-In this case, you have to send a valid [Access Token](/tokens/access-token) in the `Authorization` header, using the `Bearer` authentication scheme. An example is the [Get User Info endpoint](#get-user-info). In this scenario, you get an Access Token when you authenticate a user, and then you can make a request to the [Get User Info endpoint](#get-user-info), using that token in the `Authorization` header, in order to retrieve the user's profile.
+An example is the [Get User Info endpoint](#get-user-info). In this scenario, you get an Access Token when you authenticate a user, and then you can make a request to the [Get User Info endpoint](#get-user-info), using that token in the `Authorization` header, in order to retrieve the user's profile.
+
+### Client ID and Client Assertion
+Generate a [client assertion](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authenticate-with-private-key-jwt) containing a signed JSON Web Token (JWT) to authenticate. In the body of the request, include your Client ID, a `client_assertion_type` parameter with the value `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`, and a `client_assertion` parameter with your signed assertion. Review [Private Key JWT]( https://auth0.com/docs/get-started/authentication-and-authorization-flow/authenticate-with-private-key-jwt) for examples.
### Client ID and Client Secret
-In this case, you have to send your Client ID and Client Secret information in the request JSON body. An example is the [Revoke Refresh Token endpoint](#revoke-refresh-token). This option is available only for confidential applications (such as applications that are able to hold credentials in a secure way without exposing them to unauthorized parties).
+Send the Client ID and Client Secret. The method you can use to send this data is determined by the [Token Endpoint Authentication Method](/get-started/applications/confidential-and-public-applications/view-application-type) configured for your application.
+
+If you are using **Post**, you must send this data in the JSON body of your request.
+
+If you are using **Basic**, you must send this data in the `Authorization` header, using the `Basic` authentication scheme. To generate your credential value, concatenate your Client ID and Client Secret, separated by a colon (`:`), and encode it in Base64.
+
+An example is the [Revoke Refresh Token endpoint](#revoke-refresh-token). This option is available only for confidential applications (such as applications that are able to hold credentials in a secure way without exposing them to unauthorized parties).
### Client ID
-For public applications (such as applications that cannot hold credentials securely, like SPAs or mobile apps) we offer some endpoints that can be accessed using only the Client ID. An example is the [Implicit Grant](#implicit-grant).
+Send the Client ID. For public applications (applications that cannot hold credentials securely, such as SPAs or mobile apps), we offer some endpoints that can be accessed using only the Client ID.
+
+An example is the [Implicit Grant](#implicit-flow).
+
+### mTLS Authentication
+
+Generate a certificate, either [self-signed](/get-started/applications/configure-mtls/configure-mtls-for-a-client#self-signed-certificates) or [certificate authority signed](/get-started/applications/configure-mtls/configure-mtls-for-a-client#certificate-authority-signed-certificates). Then, [set up the customer edge network](/get-started/applications/configure-mtls/set-up-the-customer-edge) that performs the mTLS handshake.
+
+Once your edge network verifies the certificate, forward the request to the Auth0 edge network with the following headers:
+
+- The Custom Domain API key as the `cname-api-key` header.
+- The client certificate as the `client-certificate` header.
+- The client certificate CA verification status as the `client-certificate-ca-verified` header. For more information, see [Forward the Request](/get-started/applications/configure-mtls/set-up-the-customer-edge#forward-the-request-).
+
+To learn more, read [Authenticate with mTLS](/get-started/authentication-and-authorization-flow/authenticate-with-mtls).
## Parameters
@@ -44,40 +69,58 @@ For POST requests, parameters not included in the URL should be encoded as JSON
`curl --request POST --url 'https://${account.namespace}/some-endpoint' --header 'content-type: application/json' --data '{"param": "value", "param": "value"}'`
::: note
-An exception to that is the [SAML IdP-Initiated SSO Flow](#idp-initiated-sso-flow) that uses both a query string parameter and a `x-www-form-urlencoded` value.
+An exception to that is the [SAML IdP-Initiated Single Sign-on (SSO) Flow](#idp-initiated-sso-flow), which uses both a query string parameter and a `x-www-form-urlencoded` value.
:::
## Code samples
-For each endpoint you will find sample snippets you can use, in three available formats:
+For each endpoint, you will find sample snippets you can use, in three available formats:
- HTTP request
- Curl command
- JavaScript: depending on the endpoint each snippet may use the [Auth0.js library](/libraries/auth0js), Node.js code or simple JavaScript
+Each request should be sent with a Content-Type of `application/json`.
+
## Testing
-You can test the endpoints using either the [Authentication API Debugger](/extensions/authentication-api-debugger) or our preconfigured [Postman collection](https://app.getpostman.com/run-collection/2a9bc47495ab00cda178). For some endpoints both options are available.
+You can test the endpoints using the [Authentication API Debugger](/extensions/authentication-api-debugger).
-### Test with the Authentication API Debugger
+### Authentication API Debugger
The [Authentication API Debugger](/extensions/authentication-api-debugger) is an Auth0 extension you can use to test several endpoints of the Authentication API.
-If it's the first time you use it, you have to install it using the [dashboard](https://${manage_url}/#/extensions). Once you do you are ready to configure your app's settings and run your tests.
+<%= include('../../_includes/_test-this-endpoint') %>
+
+### Configure Connections
+
+1. On the *Configuration* tab, set the fields **Application** (select the application you want to use for the test) and **Connection** (the name of the social connection to use).
+
+1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications).
+
+1. At the *OAuth2 / OIDC* tab, select **OAuth2 / OIDC Login**.
+
+### Endpoint options
+Configure other endpoints with the following options:
-Note that its URL varies according to your tenant's region:
-- US West
-- Europe Central
-- Australia
+- Passwordless: On the *OAuth2 / OIDC* tab, set **Username** to the user's phone number if `connection=sms`, or the user's email if `connection=email`, and **Password** to the user's verification code. Click **Resource Owner Endpoint**.
+- SAML SSO: On the *Other Flows* tab, select **SAML**.
+- WS-Federation: On the *Other Flows* tab, select **WS-Federation**.
+- Logout: On the *Other Flows* tab, select **Logout**, or **Logout (Federated)** to log the user out of the identity provider as well.
+- Legacy Login: On the *OAuth2 / OIDC* tab, set the fields **ID Token**, **Refresh Token** and **Target Client ID**. Click **Delegation**.
+- Legacy Delegation: On the *OAuth2 / OIDC* tab, set **Username** and **Password**. Click **Resource Owner Endpoint**.
+- Legacy Resource Owner: On the *OAuth2 / OIDC* tab, set the **Username** and **Password**, then select **Resource Owner Endpoint**.
-### Test with Postman
+### Authentications flows
-If you are working with APIs, you are probably already familiar with [Postman](https://www.getpostman.com/), a development tool that enables you to configure and run API requests.
+Configure authentication flows with the following options:
+- Authorization Code Flow: On the *OAuth2 / OIDC* tab, set the field **Authorization Code** to the code you retrieved from [Authorization Code Grant](/get-started/authentication-and-authorization-flow/authorization-code-flow), and the **Code Verifier** to the key. Click **OAuth2 Code Exchange**.
+- Authorization Code Flow + PKCE: On the *OAuth2 / OIDC* tab, set the field **Authorization Code** to the code you retrieved from [Authorization Code Grant](/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce), and the **Code Verifier** to the key. Click **OAuth2 Code Exchange**.
+- Client Credential Flow: On the *OAuth2 / OIDC* tab, select **OAuth2 Client Credentials**.
-We have preconfigured a collection that you can [download](https://app.getpostman.com/run-collection/2a9bc47495ab00cda178). You will have to configure some environment variables to customize the requests. For more information on this, refer to [Using the Auth0 API with our Postman Collections](/api/postman).
## Errors
-When an error occurs, you will receive an error object. All error objects have an error code and an error description so that your applications can tell what the problem is.
+When an error occurs, you will receive an error object. Most of these error objects contain an error code and an error description so that your applications can more efficiently identify the problem.
If you get an `4xx` HTTP response code, then you can assume that there is a bad request from your end. In this case, check the [Standard Error Responses](#standard-error-responses) for more context.
@@ -93,10 +136,10 @@ If you exceed the provided rate limit for a given endpoint, you will receive the
For details on rate limiting, refer to [Auth0 API Rate Limit Policy](/policies/rate-limits).
-Note that for database connections Auth0 limits certain types of repeat login attempts depending on the user account and IP address. For details, refer to [Rate Limits on User/Password Authentication](/connections/database/rate-limits).
+Note that for database connections Auth0 limits certain types of repeat login attempts depending on the user account and IP address. For details, refer to [Rate Limits on User/Password Authentication](/policies/rate-limit-policy/database-connections-rate-limits).
## Support
-If you have problems or need help with your case you can always reach out to our [Support](${env.DOMAIN_URL_SUPPORT}).
+If you have problems or need help with your case, you can always reach out to our [Support](${env.DOMAIN_URL_SUPPORT}).
Note that if you have a free subscription plan, and you are not in your 22-day trial period, you will not be able to access or open tickets in the [Support Center](${env.DOMAIN_URL_SUPPORT}). In this case, you can seek support through the [Auth0 Community](https://community.auth0.com/). For more info on our support program, refer to [Support Options](/support).
diff --git a/articles/api/authentication/_login.md b/articles/api/authentication/_login.md
index fa63346cbd..ede24026ba 100644
--- a/articles/api/authentication/_login.md
+++ b/articles/api/authentication/_login.md
@@ -1,5 +1,13 @@
+
# Login
+<%= include('../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "GET",
+ "path": "/authorize",
+ "link": "#social"
+}) %>
+
## Social
```http
@@ -21,7 +29,7 @@ GET https://${account.namespace}/authorize?
domain: '${account.namespace}',
clientID: '${account.clientId}'
});
-
+
// Trigger login with google
webAuth.authorize({
connection: 'google-oauth2'
@@ -39,14 +47,9 @@ GET https://${account.namespace}/authorize?
```
-<%= include('../../_includes/_http-method', {
- "http_badge": "badge-primary",
- "http_method": "GET",
- "path": "/authorize",
- "link": "#social"
-}) %>
+You can connect your Auth0 service to a social identity provider and allow your users to log in to your application via Facebook, Google, Apple, or other supported providers. To learn more about supported providers, visit [Marketplace](https://marketplace.auth0.com/features/social-connections).
-Use this endpoint to authenticate a user with a social provider. It will return a `302` redirect to the social provider specified in `connection`.
+To authenticate users with a social provider, make a `GET` call to the `/authorize` endpoint. It will return a `302` redirect to the social provider specified in the `connection` parameter.
::: note
Social connections only support browser-based (passive) authentication because most social providers don't allow a username and password to be entered into applications that they don't own. Therefore, the user will be redirected to the provider's sign in page.
@@ -56,40 +59,26 @@ Social connections only support browser-based (passive) authentication because m
| Parameter | Description |
|:-----------------|:------------|
-| `response_type` Required | Use `code` for server side flows and `token` for application side flows |
+| `response_type` Required | Specifies the token type. Use `code` for server side flows and `token` for application side flows |
| `client_id` Required | The `client_id` of your application |
| `connection` | The name of a social identity provider configured to your application, for example `google-oauth2` or `facebook`. If null, it will redirect to the [Auth0 Login Page](https://${account.namespace}/login) and show the Login Widget. |
-| `redirect_uri` Required | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
+| `redirect_uri` Required | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. Specify the `redirect_uri` under your [Application's Settings](${manage_url}/#/applications).|
| `state` Recommended | An opaque value the applications adds to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks. |
-| `ADDITIONAL_PARAMETERS` | Append any additional parameter to the end of your request, and it will be sent to the provider. For example, `access_type=offline` (for Google Refresh Tokens) , `display=popup` (for Windows Live popup mode). |
-
-### Test with Authentication API Debugger
-
-<%= include('../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the fields **Application** (select the application you want to use for the test) and **Connection** (the name of the social connection to use).
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, click **OAuth2 / OIDC Login**.
+| `ADDITIONAL_PARAMETERS` | Append any additional parameter to the end of your request, and it will be sent to the provider. For example, `access_type=offline` (for Google Refresh Tokens) , `display=popup` (for Windows Live popup mode). |
### Remarks
-- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-- If `response_type=token`, after the user authenticates on the provider, it will redirect to your application `callback URL` passing the `access_token` and `id_token` in the address `location.hash`. This is used for Single Page Apps and also on Native Mobile SDKs.
+- If `response_type=token`, after the user authenticates on the provider, it will redirect to your application `callback URL` passing the Access Token and ID Token in the address `location.hash`. This is used for Single-Page Apps and also on Native Mobile SDKs.
- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
+### Learn More
-### More Information
-
-- [Supported Social Identity Providers](/identityproviders#social)
+- [Supported Social Identity Providers](https://marketplace.auth0.com/features/social-connections)
- [Custom Social Connections](/connections/social/oauth2)
-- [Using the State Parameter](/protocols/oauth2/oauth-state)
+- [State Parameter](/secure/attack-protection/state-parameters)
- [Auth0.js /authorize Method Reference](/libraries/auth0js#webauth-authorize-)
-
## Database/AD/LDAP (Passive)
```http
@@ -98,6 +87,7 @@ GET https://${account.namespace}/authorize?
client_id=${account.clientId}&
connection=CONNECTION&
redirect_uri=${account.callback}&
+ scope=openid%20profile%20email&
state=STATE
```
@@ -110,64 +100,46 @@ GET https://${account.namespace}/authorize?
domain: '${account.namespace}',
clientID: '${account.clientId}'
});
-
+
// Calculate URL to redirect to
var url = webAuth.client.buildAuthorizeUrl({
clientID: '${account.clientId}', // string
responseType: 'token', // code or token
redirectUri: '${account.callback}',
+ scope: 'openid profile email'
state: 'YOUR_STATE'
});
-
+
// Redirect to url
// ...
```
-<%= include('../../_includes/_http-method', {
- "http_badge": "badge-primary",
- "http_method": "GET",
- "path": "/authorize",
- "link": "#database-ad-ldap-passive-"
-}) %>
-
-Use this endpoint for browser based (passive) authentication. It returns a `302` redirect to the [Auth0 Login Page](https://${account.namespace}/login) that will show the Login Widget where the user can login with email and password.
+Use the Auth0 user store or your own database to store and manage username and password credentials. If you have your own user database, you can use it as an identity provider in Auth0 to authenticate users. When you make a `GET` call to the `/authorize` endpoint for browser based (passive) authentication. It returns a `302` redirect to the [Auth0 Login Page](https://${account.namespace}/login) that will show the Login Widget where the user can log in with email and password.
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `response_type` Required | Use `code` for server side flows and `token` for application side flows. |
+| `response_type` Required | Specifies the token type. Use `code` for server side flows and `token` for application side flows. |
| `client_id` Required | The `client_id` of your application. |
| `connection` | The name of the connection configured to your application. If null, it will redirect to the [Auth0 Login Page](https://${account.namespace}/login) and show the Login Widget using the first database connection. |
-| `redirect_uri` Required | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
+| `redirect_uri` Required | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. Specify the `redirect_uri` under your [Application's Settings](${manage_url}/#/applications).|
+| `scope` Recommended | OIDC scopes and custom API scopes. For example: `openid read:timesheets`. Include `offline_access` to get a Refresh Token.|
| `state` Recommended | An opaque value the applications adds to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks. |
-
-### Test with Authentication API Debugger
-
-<%= include('../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the fields **Application** (select the application you want to use for the test) and **Connection** (the name of the social connection to use).
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, click **OAuth2 / OIDC Login**.
-
-
### Remarks
-- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-- If `response_type=token`, after the user authenticates, it will redirect to your application `callback URL` passing the `access_token` and `id_token` in the address `location.hash`. This is used for Single Page Apps and also on Native Mobile SDKs.
+- If `response_type=token`, after the user authenticates, it will redirect to your application `callback URL` passing the Access Token and ID Token in the address `location.hash`. This is used for Single-Page Apps and also on Native Mobile SDKs.
- The main difference between passive and active authentication is that the former happens in the browser through the [Auth0 Login Page](https://${account.namespace}/login) and the latter can be invoked from anywhere (a script, server to server, and so forth).
- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
-### More Information
+### Learn More
- [Database Identity Providers](/connections/database)
-- [Rate Limits on User/Password Authentication](/connections/database/rate-limits)
+- [Rate Limits on User/Password Authentication](/policies/rate-limit-policy/database-connections-rate-limits)
- [Active Directory/LDAP Connector](/connector)
-- [Using the State Parameter](/protocols/oauth2/oauth-state)
+- [State Parameter](/protocols/oauth2/oauth-state)
- [Auth0.js /authorize Method Reference](/libraries/auth0js#webauth-authorize-)
## Enterprise (SAML and Others)
@@ -190,69 +162,212 @@ GET https://${account.namespace}/authorize?
domain: '${account.namespace}',
clientID: '${account.clientId}'
});
-
- // Trigger login using redirect with credentials to enterprise connections
- webAuth.redirect.loginWithCredentials({
- connection: 'Username-Password-Authentication',
- username: 'testuser',
- password: 'testpass',
- scope: 'openid'
- });
- // Trigger login using popup mode with credentials to enterprise connections
- webAuth.popup.loginWithCredentials({
- connection: 'Username-Password-Authentication',
- username: 'testuser',
- password: 'testpass',
- scope: 'openid'
+ // Calculate URL to redirect to
+ var url = webAuth.client.buildAuthorizeUrl({
+ clientID: 'YOUR_CLIENT_ID', // string
+ responseType: 'token', // code or token
+ redirectUri: 'https://YOUR_APP/callback',
+ scope: 'openid profile email'
+ state: 'YOUR_STATE'
});
+
+ // Redirect to url
+ // ...
```
-<%= include('../../_includes/_http-method', {
- "http_badge": "badge-primary",
- "http_method": "GET",
- "path": "/authorize",
- "link": "#enterprise-saml-and-others-"
-}) %>
-
-Use this endpoint for passive authentication. It returns a `302` redirect to the SAML Provider (or Windows Azure AD and the rest, as specified in the `connection`) to enter their credentials.
+You can connect your Auth0 service to an enterprise identity provider and allow your users to log in to your application via Microsoft Azure Active Directory, Google Workspace, Okta Workforce, or other supported providers. To learn more about supported providers, visit [Auth0 Marketplace](https://marketplace.auth0.com/features/enterprise-connections).
+Make a `GET` call to the `/authorize` endpoint for passive authentication. It returns a `302` redirect to the SAML Provider (or Windows Azure AD and the rest, as specified in the `connection`) to enter their credentials.
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `response_type` Required | Use `code` for server side flows, `token` for application side flows. |
+| `response_type` Required | Specifies the token type. Use `code` for server side flows, `token` for application side flows. |
| `client_id` Required | The `client_id` of your application. |
| `connection` | The name of the connection configured to your application. If null, it will redirect to the [Auth0 Login Page](https://${account.namespace}/login) and show the Login Widget using the first database connection. |
-| `redirect_uri` Required | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
+| `redirect_uri` Required | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. Specify the `redirect_uri` under your [Application's Settings](${manage_url}/#/applications).|
| `state` Recommended | An opaque value the applications adds to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks. |
+### Remarks
+
+- If no `connection` is specified, it will redirect to the [Login Page](https://${account.namespace}/login) and show the Login Widget.
+- If `response_type=token`, after the user authenticates, it will redirect to your application `callback URL` passing the Access Token and ID Token in the address `location.hash`. This is used for Single-Page Apps and also on Native Mobile SDKs.
+- Additional parameters can be sent that will be passed to the provider.
+- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
+
+### Learn More
-### Test with Authentication API Debugger
+- [SAML](/protocols/saml)
+- [Obtain a Client Id and Client Secret for Microsoft Azure Active Directory](/connections/enterprise/azure-active-directory)
+- [State Parameter](/protocols/oauth2/oauth-state)
+- [Auth0.js /authorize Method Reference](/libraries/auth0js#webauth-authorize-)
-<%= include('../../_includes/_test-this-endpoint') %>
+## Back-Channel Login
-1. At the *Configuration* tab, set the fields **Application** (select the application you want to use for the test) and **Connection** (the name of the social connection to use).
+:::note
+This feature is currently in Early Access. To request access, contact your Technical Account Manager.
+:::
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
+The Back-Channel Login endpoint enables applications to send an authentication request to a user’s phone, or the authentication device, provided they have an app installed and are enrolled for [push notifications using the Guardian SDK](/secure/multi-factor-authentication/auth0-guardian#enroll-in-push-notifications).
-1. At the *OAuth2 / OIDC* tab, click **OAuth2 / OIDC Login**.
+Use the Back-Channel Login endpoint to authenticate users for the following use cases:
+- Users are not in front of the application that requires authentication, such as when they're telephoning a call center.
+- The consumption device, or the device that helps the user consume a service, is insecure for sensitive operations e.g. web browser for financial transactions.
+- The consumption device has limited interactive capability e.g. e-bicycles or e-scooters.
+
+<%= include('../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "POST",
+ "path": "/bc-authorize",
+ "link": "#back-channel-login"
+}) %>
+
+```http
+curl --location 'https://[TENANT_DOMAIN]/bc-authorize' \
+--header 'Content-Type: application/x-www-form-urlencoded' \
+--data-urlencode 'client_id=[CLIENT ID]' \
+--data-urlencode 'client_secret=[CLIENT SECRET]' \
+--data-urlencode 'binding_message=[YOUR BINDING MESSAGE]' \
+--data-urlencode 'login_hint={ "format": "iss_sub", "iss":
+"https://[TENANT].auth0.com/", "sub": "auth0|[USER ID]" }' \
+--data-urlencode 'scope=openid'
+```
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `client_id` Required | Client ID of your application. |
+| `binding_message` Required | Human-readable string displayed on both the device calling `/bc-authorize` and the user’s authentication device (e.g. phone) to ensure the user is approves the correct request. For example: `ABC-123-XYZ`. |
+| `login_hint` Required | String containing information about the user to contact for authentication. It uses the [IETF9493 standard for Subject Identifiers for Security Event Tokens](https://datatracker.ietf.org/doc/html/rfc9493). Auth0 only supports the [Issuer and Identifier format](https://datatracker.ietf.org/doc/html/rfc9493#name-issuer-and-subject-identifi). For an example login hint, review the [Remarks](#remarks). |
+| `scope` Required | Space-separated list of OIDC and custom API scopes. For example: `openid read:timesheets edit:timesheets`. Include `offline_access` to get a refresh token. At a minimum, you must include the scope `openid`. |
+| `audience` Optional | Unique identifier of the audience for an issued token. If you require an access token for an API, pass the unique identifier of the target API you want to access. |
+| `request_expiry` Optional | To configure a custom expiry time in seconds for this request, pass a number between 1 and 300. If not provided, expiry defaults to 300 seconds. |
+
+### Response Body
+
+If the request is successful, you should receive a response like the following:
+
+```http
+{
+ "auth_req_id": "eyJh...",
+ "expires_in": 300,
+ "interval": 5
+}
+```
+
+The `auth_req_id` value should be kept as it is used later in the flow to identify the authentication request.
+
+The `expires_in` value tells you how many seconds you have until the authentication request expires.
+
+The `interval` value tells you how many seconds you must wait between poll requests.
+
+The request should be approved or rejected on the user’s authentication device using the Guardian SDK.
### Remarks
-- If no `connection` is specified, it will redirect to the [Login Page](https://${account.namespace}/login) and show the Login Widget.
-- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-- If `response_type=token`, after the user authenticates, it will redirect to your application `callback URL` passing the `access_token` and `id_token` in the address `location.hash`. This is used for Single Page Apps and also on Native Mobile SDKs.
-- Additional parameters can be sent that will be passed to the provider.
-- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
-- In order to use `loginWithCredentials`, auth0.js needs to make cross-origin calls. Check the [Cross-Origin Authentication](/cross-origin-authentication) article to understand the limitations of this approach.
+The following code sample is an example login hint:
-### More Information
+ ```http
+ {
+ "format": "iss_sub",
+ "iss": "https://[TENANT_DOMAIN]/",
+ "sub": "auth0|[USER ID]"
+ }
+ ```
-- [SAML](/protocols/saml)
-- [Obtain a Client Id and Client Secret for Microsoft Azure Active Directory](/connections/enterprise/azure-active-directory)
-- [Using the State Parameter](/protocols/oauth2/oauth-state)
-- [Auth0.js /authorize Method Reference](/libraries/auth0js#webauth-authorize-)
+White space is not significant. Replace the `[TENANT_DOMAIN]` with your tenant domain or custom domain. Replace the `[USER ID]` with a valid `user_id` for the authorizing user returned from the [User Search APIs](https://auth0.com/docs/manage-users/user-search).
+
+Include an optional parameter for application authentication in the request:
+
+- Client Secret with HTTP Basic auth, in which case no parameters are required. The `client_id` and `client_secret` are passed in a header.
+- Client Secret Post, in which case the `client_id` and `client_secret` are required.
+- Private Key JWT, where the `client_id`, `client_assertion` and `client_assertion` type are required.
+- mTLS, where the `client_id` parameter is required and the `client-certificate` and `client-certificate-ca-verified` headers are required.
+
+<%= include('../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#post-token"
+}) %>
+
+```http
+curl --location 'https://[TENANT_DOMAIN]/oauth/token' \
+--header 'Content-Type: application/x-www-form-urlencoded' \
+--data-urlencode 'client_id=[CLIENT ID]' \
+--data-urlencode 'client_secret=[CLIENT SECRET]' \
+--data-urlencode 'auth_req_id=[FROM THE BC-AUTHORIZE RESPONSE]' \
+--data-urlencode 'grant_type=urn:openid:params:grant-type:ciba'
+```
+
+To check on the status of a Back-Channel Login flow, poll the `/oauth/token` endpoint at regular intervals by passing the following:
+
+- `auth_req_id` returned from the call to `/bc-authorize`
+- `urn:openid:params:grant-type:ciba` grant type
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `client_id` Required | Client ID of your application |
+| `auth_req_id` Required | Used to reference the authentication request. Returned from the call to `/bc-authorize` |
+| `grant_type` Required | Must be set to `urn:openid:params:grant-type:ciba` |
+
+### Response Body
+
+If the authorizing user has not yet approved or rejected the request, you should receive a response like the following:
+
+```http
+{
+ "error": "authorization_pending",
+ "error_description": "The end-user authorization is pending"
+}
+```
+
+If the authorizing user rejects the request, you should receive a response like the following:
+
+```http
+{
+ "error": "access_denied",
+ "error_description": "The end-user denied the authorization request or it
+has been expired"
+}
+```
+
+If you are polling too quickly (faster than the interval value returned from `/bc-authorize`), you should receive a response like the following:
+
+```http
+{
+ "error": "slow_down",
+ "error_description": "You are polling faster than allowed. Try again in 10 seconds."
+}
+```
+
+In addition, Auth0 will add the the [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header to the response indicating how many seconds to wait before attempting to poll again. If you consistently poll too frequently, the number of seconds you must wait increases.
+
+If the authorizing user has approved the push notification, the call returns the ID token and access token (and potentially a refresh token):
+
+```http
+{
+ "access_token": "eyJh...",
+ "id_token": "eyJh...",
+ "expires_in": 86400,
+ "scope": "openid"
+}
+```
+
+Once you have exchanged an `auth_req_id` for an ID or access token, it is no longer usable.
+
+### Remarks
+
+Include an optional parameter for application authentication in the request:
+
+- Client Secret with HTTP Basic auth, in which case no parameters are required. The `client_id` and `client_secret` are passed in a header.
+- Client Secret Post, in which case the `client_id` and `client_secret` are required.
+- Private Key JWT, where the `client_id`, `client_assertion` and `client_assertion` type are required.
+- mTLS, where the `client_id` parameter is required and the `client-certificate` and `client-certificate-ca-verified` headers are required.
\ No newline at end of file
diff --git a/articles/api/authentication/_logout.md b/articles/api/authentication/_logout.md
index e2c0661bd1..930bf1a337 100644
--- a/articles/api/authentication/_logout.md
+++ b/articles/api/authentication/_logout.md
@@ -1,4 +1,13 @@
+
# Logout
+## Auth0 Logout
+
+<%= include('../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "GET",
+ "path": "/v2/logout",
+ "link": "#logout"
+}) %>
```http
GET https://${account.namespace}/v2/logout?
@@ -30,43 +39,158 @@ curl --request GET \
```
+Use this endpoint to logout a user. If you want to navigate the user to a specific URL after the logout, set that URL at the `returnTo` parameter. The URL should be included in any the appropriate `Allowed Logout URLs` list:
+- If the `client_id` parameter is included, the `returnTo` URL must be listed in the `Allowed Logout URLs` set at the application level. To learn more, read [Log Users Out of Applications](/authenticate/login/logout/log-users-out-of-applications).
+- If the `client_id` parameter is NOT included, the `returnTo` URL must be listed in the `Allowed Logout URLs` set at the tenant level. To learn more, read [Log Users Out of Auth0](/authenticate/login/logout/log-users-out-of-auth0).
+- If the `client_id` parameter is included and the `returnTo` URL is NOT set, the server returns the user to the first Allowed Logout URLs set in the Dashboard. To learn more, read [Log Users Out of Applications](/authenticate/login/logout/log-users-out-of-applications).
+
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `returnTo` | URL to redirect the user after the logout. |
+| `client_id` | The `client_id` of your application. |
+| `federated` | Add this query string parameter to the logout URL, to log the user out of their identity provider, as well: `https://${account.namespace}/v2/logout?federated`. |
+
+### Remarks
+
+- Logging the user out of their identity provider is not common practice, so think about the user experience before you use the `federated` query string parameter.
+- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
+
+### Learn More
+
+- [Logout](/logout)
+
+## OIDC Logout
<%= include('../../_includes/_http-method', {
"http_badge": "badge-primary",
"http_method": "GET",
- "path": "/v2/logout",
+ "path": "/oidc/logout",
"link": "#logout"
}) %>
-Use this endpoint to logout a user. If you want to navigate the user to a specific URL after the logout, set that URL at the `returnTo` parameter. The URL should be included in any the appropriate `Allowed Logout URLs` list:
-- If the `client_id` parameter is included, the `returnTo` URL must be listed in the `Allowed Logout URLs` set at the application level (see [Setting Allowed Logout URLs at the App Level](/logout#set-the-allowed-logout-urls-at-the-application-level)).
-- If the `client_id` parameter is NOT included, the `returnTo` URL must be listed in the `Allowed Logout URLs` set at the tenant level (see [Setting Allowed Logout URLs at the Tenant Level](/logout#set-the-allowed-logout-urls-at-the-tenant-level)).
+```http
+GET https://${account.namespace}/oidc/logout?
+ post_logout_redirect_uri=LOGOUT_URL&
+ id_token_hint=ID_TOKEN_HINT
+```
+
+```shell
+curl --request GET \
+ --url 'https://${account.namespace}/oidc/logout' \
+ --header 'content-type: application/json' \
+ --data-raw '
+ {
+ "client_id":"${account.clientId}",
+ "post_logout_redirect_uri":"LOGOUT_URL",
+ "id_token_hint":"ID_TOKEN_HINT"
+ }'
+```
+
+```javascript
+// Script uses auth0.js. See Remarks for details.
+
+
+```
+
+Use this endpoint to logout a user. If you want to navigate the user to a specific URL after the logout, set that URL at the `post_logout_redirect_uri` parameter. The URL should be included in the appropriate `Allowed Logout URLs` list:
+
+- If the `id_token_hint` parameter is included:
+ - When the `client_id` parameter is included, the server uses the URL from the `aud` claim in the `id_token_hint` to select which of the `Allowed Logout URLs` to use from the application specified by the `client_id`.
+ - When the `client_id` parameter is NOT included, the server uses the URL from the `aud` claim in the `id_token_hint` to select which of the `Allowed Logout URLs` at the tenant level to use.
+- If the `id_token_hint` parameter is not included:
+ - If the `client_id` parameter is included, the `post_logout_redirect_uri` URL must be listed in the `Allowed Logout URLs` set at the application level.
+ - If the `client_id` parameter is NOT included, the `post_logout_redirect_uri` URL must be listed in the `Allowed Logout URLs` set at the tenant level.
+ - If the `client_id` parameter is included and the `post_logout_redirect_uri` URL is NOT set, the server returns the user to the first `Allowed Logout URLs` set in Auth0 Dashboard.
+
+ To learn more, read [Log Users Out of Auth0 with OIDC Endpoint](/authenticate/login/logout/log-users-out-of-auth0).
### Request Parameters
-| Parameter | Description |
-|:-----------------|:------------|
-| `returnTo ` | URL to redirect the user after the logout. |
-| `client_id` | The `client_id` of your application. |
-| `federated` | Add this querystring parameter to the logout URL, to log the user out of their identity provider, as well: `https://${account.namespace}/v2/logout?federated`. |
+| Parameter | Description |
+| :------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `id_token_hint` Recommended | Previously issued ID Token for the user. This is used to indicate which user to log out. |
+| `logout_hint` Optional | Optional `sid` (session ID) value to indicate which user to log out. Should be provided when `id_token_hint` is not available. |
+| `post_logout_redirect_uri` Optional | URL to redirect the user after the logout. |
+| `client_id` Optional | The `client_id` of your application. |
+| `federated` Optional | Add this query string parameter to log the user out of their identity provider: `https://YOUR_DOMAIN/oidc/logout?federated`. |
+| `state` Optional | An opaque value the applications adds to the initial request that the authorization server includes when redirecting the back to the`post_logout_redirect_uri`. |
+| `ui_locales` Optional | Space-delimited list of locales used to constrain the language list for the request. The first locale on the list must match the enabled locale in your tenant |
+### Remarks
-### Test with Authentication API Debugger
+- Logging the user out of their social identity provider is not common practice, so think about the user experience before you use the `federated` query string parameter with social identity providers.
+- If providing both `id_token_hint` and `logout_hint`, the `logout_hint` value must match the `sid` claim from the id_token_hint.
+- If providing both `id_token_hint` and `client_id`, the `client_id` value must match the `aud` claim from the `id_token_hint`.
+- If `id_token_hint` is not provided, then the user will be prompted for consent unless a `logout_hint` that matches the user's session ID is provided.
+- The `POST` HTTP method is also supported for this request. When using `POST`, the request parameters should be provided in the request body as form parameters instead of the query string. The federated parameter requires a value of `true` or `false`.
+- This conforms to the [OIDC RP-initiated Logout Specification](https://openid.net/specs/openid-connect-rpinitiated-1_0.html).
-<%= include('../../_includes/_test-this-endpoint') %>
+### Learn More
-1. At the *Configuration* tab, set the fields **Application** (select the application you want to use for the test) and **Connection** (the name of the social connection to use).
+- [Logout](/logout)
+- [Use the OIDC Endpoint to Log Users Out of Auth0](/logout/log-users-out-of-auth0)
+- [OIDC RP-initiated Logout Specification](https://openid.net/specs/openid-connect-rpinitiated-1_0.html)
-1. Copy the **Callback URL** and set it as part of the **Allowed Logout URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
+## SAML Logout
-1. At the *Other Flows* tab, click **Logout**, or **Logout (Federated)** to log the user out of the identity provider as well.
+```http
+POST https://${account.namespace}/samlp/CLIENT_ID/logout
+```
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/samlp/CLIENT_ID/logout' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data '{SAML_LOGOUT_REQUEST}'
+```
-### Remarks
+Use this endpoint to log out a user from an Auth0 tenant configured as a SAML identity provider (IdP).
-- Logging the user out of their identity provider is not common practice, so think about the user experience before you use the `federated` querystring parameter.
-- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
+Logout behavior is determined by the configuration of the SAML2 Web App addon for the application on the Auth0 tenant acting as the SAML IdP. To learn more, read [Log Users Out of SAML Identity Providers](https://auth0.com/docs/authenticate/login/logout/log-users-out-of-saml-idps#configure-slo-when-auth0-is-the-saml-idp).
-### More Information
+### Request Parameters
+| Parameter | Description |
+|:--|:--|
+| `CLIENT_ID` | Client ID of your application configured with the [SAML2 Web App addon](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/enable-saml2-web-app-addon). |
+| `SAML_LOGOUT_REQUEST` | SAML `` message. |
+
+### Remarks
+- The POST body must contain a valid SAML `` message. To learn more, read [Assertions and Protocols for the OASIS Security Assertion Markup Language (SAML) V2.0 on Oasis](https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf).
+
+### Learn More
- [Logout](/logout)
+- [Log Users Out of SAML Identity Providers](https://auth0.com/docs/authenticate/login/logout/log-users-out-of-saml-idps)
+
+## Global Token Revocation
+<%= include('../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "POST",
+ "path": "/oauth/global-token-revocation/connection/YourConnectionName",
+ "link": "#logout"
+}) %>
+
+Use this endpoint with the [Okta Workforce Identity Cloud Universal Logout](https://developer.okta.com/docs/guides/oin-universal-logout-overview/) to log users out of your applications. To learn more, read [Universal Logout](https://auth0.com/docs/authenticate/login/logout/universal-logout).
+
+### Request Parameters
+| Parameter | Description |
+| :-- | :-- |
+| `subject` | `{ "format": "iss_sub", "iss": "https://issuer.example.com/", "sub": "145234573" }` |
+
+### Remarks
+- A request to this endpoint revokes sessions cookies and refresh tokens, but not access tokens.
+- You must authenticate at the endpoint before revoking user sessions. Review [Endpoint Authentication](https://developer.okta.com/docs/guides/oin-universal-logout-overview/#endpoint-authentication).
diff --git a/articles/api/authentication/_multifactor-authentication.md b/articles/api/authentication/_multifactor-authentication.md
index 83fc1cb202..32c6a59802 100644
--- a/articles/api/authentication/_multifactor-authentication.md
+++ b/articles/api/authentication/_multifactor-authentication.md
@@ -1,18 +1,18 @@
-# Multifactor Authentication
+# Multi-factor Authentication
-The Multifactor Authentication (MFA) API endpoints allow you to enforce MFA when users interact with [the Token endpoints](#get-token), as well enroll and manage user authenticators.
+The Multi-factor Authentication (MFA) API endpoints allow you to enforce MFA when users interact with [the Token endpoints](#get-token), as well as enroll and manage user authenticators.
First, request a challenge based on the challenge types supported by the application and user. If you know that one-time password (OTP) is supported, you can skip the challenge request.
-Next, verify the multifactor authentication using the `/oauth/token` endpoint and the specified challenge type: a one-time password (OTP), a recovery code, or an out-of-band (OOB) challenge.
+Next, verify the multi-factor authentication using the `/oauth/token` endpoint and the specified challenge type: a one-time password (OTP), a recovery code, or an out-of-band (OOB) challenge.
-For more information, check out:
+To learn more, read:
-- [Multifactor Authentication and Resource Owner Password](/api-auth/tutorials/multifactor-resource-owner-password)
-- [Multifactor Authentication API](/multifactor-authentication/api)
-- [Multifactor Authentication in Auth0](/multifactor-authentication)
+- [Multi-factor Authentication and Resource Owner Password](/mfa/guides/mfa-api/multifactor-resource-owner-password)
+- [Multi-factor Authentication API](/mfa/concepts/mfa-api)
+- [Multi-factor Authentication in Auth0](/mfa)
-## Challenge request
+## Challenge Request
```http
POST https://${account.namespace}/mfa/challenge
@@ -62,6 +62,7 @@ Content-Type: application/json
```
> RESPONSE SAMPLE FOR OOB WITHOUT BINDING METHOD:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -72,6 +73,7 @@ Content-Type: application/json
```
> RESPONSE SAMPLE FOR OOB WITH BINDING METHOD:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -82,21 +84,14 @@ Content-Type: application/json
}
```
-<%= include('../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": "/mfa/challenge",
- "link": "#multifactor-authentication"
-}) %>
-
-Request a challenge based on the challenge types supported by the application and user.
+Request a challenge for multi-factor authentication (MFA) based on the challenge types supported by the application and user.
The `challenge_type` is how the user will get the challenge and prove possession. Supported challenge types include:
- `otp`: for one-time password (OTP)
-- `oob`: for SMS messages or out-of-band (OOB)
+- `oob`: for SMS/Voice messages or out-of-band (OOB)
-If OTP is supported by the user and you don't want to request a different factor, you can skip the challenge request and [verify the multifactor authentication with a one-time password](#verify-with-one-time-password-otp-).
+If OTP is supported by the user and you don't want to request a different factor, you can skip the challenge request and [verify the multi-factor authentication with a one-time password](#verify-with-one-time-password-otp-).
### Request Parameters
@@ -104,10 +99,11 @@ If OTP is supported by the user and you don't want to request a different factor
|:-----------------|:------------|
| `mfa_token` Required | The token received from `mfa_required` error. |
| `client_id` Required | Your application's Client ID. |
-| `client_secret` | Your application's Client Secret. **Required** when the **Token Endpoint Authentication Method** field at your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings) is `Post` or `Basic`. |
+| `client_assertion`| A JWT containing a signed assertion with your application credentials. Required when Private Key JWT is your application authentication method.|
+| `client_assertion_type`| The value is `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method.|
+| `client_secret` | Your application's Client Secret. Required when the Token Endpoint Authentication Method field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. |
| `challenge_type` | A whitespace-separated list of the challenges types accepted by your application. Accepted challenge types are `oob` or `otp`. Excluding this parameter means that your client application accepts all supported challenge types. |
-| `oob_channel` | **(early access users only)** The channel to use for OOB. Can only be provided when `challenge_type` is `oob`. Accepted channel types are `sms` or `auth0`. Excluding this parameter means that your client application will accept all supported OOB channels. |
-| `authenticator_id` | **(early access users only)** The ID of the authenticator to challenge. You can get the ID by querying the list of available authenticators for the user as explained on [List authenticators](#list-authenticators) below. |
+| `authenticator_id` | The ID of the authenticator to challenge. You can get the ID by querying the list of available authenticators for the user as explained on [List authenticators](#list-authenticators) below. |
### Remarks
@@ -115,31 +111,27 @@ If OTP is supported by the user and you don't want to request a different factor
- Auth0 chooses the challenge type based on the application's supported types and types the user is enrolled with.
- An `unsupported_challenge_type` error is returned if your application does not support any of the challenge types the user has enrolled with.
- An `unsupported_challenge_type` error is returned if the user is not enrolled.
-- **(early access only)** If the user is not enrolled, you will get a `association_required` error, indicating the user needs to enroll to use MFA. Check [Add an authenticator](#add-an-authenticator) below on how to proceed.
+- If the user is not enrolled, you will get a `association_required` error, indicating the user needs to enroll to use MFA. Read [Add an authenticator](#add-an-authenticator) below on how to proceed.
-### More information
+### Learn More
-- [Associate a New Authenticator for Use with Multifactor Authentication](/multifactor-authentication/api/challenges)
+* [Authenticate With Resource Owner Password Grant and MFA](/mfa/guides/mfa-api/authenticate)
+* [Manage Authenticator Factors using the MFA API](/mfa/guides/mfa-api/manage)
-## Verify with one-time password (OTP)
+## Verify with One-Time Password (OTP)
```http
POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET",
- "mfa_token": "MFA_TOKEN",
- "grant_type": "http://auth0.com/oauth/grant-type/mfa-otp",
- "otp": "OTP_CODE"
-}
+Content-Type: application/x-www-form-urlencoded
+
+client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&mfa_token=MFA_TOKEN&grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-otp&otp=OTP_CODE
```
```shell
curl --request POST \
--url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"mfa_token":"MFA_TOKEN", "otp":"OTP_CODE", "grant_type": "http://auth0.com/oauth/grant-type/mfa-otp", "client_id": "${account.clientId}", "client_secret": "YOUR_CLIENT_SECRET"}'
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'mfa_token=MFA_TOKEN&otp=OTP_CODE&grant_type=http://auth0.com/oauth/grant-type/mfa-otp&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET'
```
```javascript
@@ -147,14 +139,14 @@ var request = require("request");
var options = { method: 'POST',
url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
{ mfa_token: 'MFA_TOKEN',
otp: 'OTP_CODE',
grant_type: 'http://auth0.com/oauth/grant-type/mfa-otp',
client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
+ client_secret: 'YOUR_CLIENT_SECRET' }
+ };
request(options, function (error, response, body) {
if (error) throw new Error(error);
@@ -164,6 +156,7 @@ request(options, function (error, response, body) {
```
> RESPONSE SAMPLE FOR OTP:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -181,7 +174,7 @@ Content-Type: application/json
"link": "#multifactor-authentication"
}) %>
-Verifies multifactor authentication (MFA) using a one-time password (OTP).
+Verifies multi-factor authentication (MFA) using a one-time password (OTP).
To verify MFA with an OTP, prompt the user to get the OTP code, then make a request to the `/oauth/token` endpoint. The request must have the OTP code, the `mfa_token` you received (from the `mfa_required` error), and the `grant_type` set to `http://auth0.com/oauth/grant-type/mfa-otp`.
@@ -192,35 +185,31 @@ The response is the same as responses for `password` or `http://auth0.com/oauth/
| Parameter | Description |
|:-----------------|:------------|
| `grant_type` Required | Denotes the flow you are using. For OTP MFA use `http://auth0.com/oauth/grant-type/mfa-otp`. |
-| `client_id` Required | Your application's Client ID. |
-| `client_secret` | Your application's Client Secret. **Required** when the **Token Endpoint Authentication Method** field at your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings) is `Post` or `Basic`. |
+| `client_id` | Your application's Client ID. |
+| `client_assertion`| A JWT containing a signed assertion with your application credentials. Required when Private Key JWT is your application authentication method.|
+| `client_assertion_type`| The value is `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method. |
+| `client_secret` | Your application's Client Secret. Required when the Token Endpoint Authentication Method field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. |
| `mfa_token` Required | The `mfa_token` you received from `mfa_required` error. |
| `otp` Required | OTP Code provided by the user. |
-### More informationm
+### Learn More
-- [Associate an OTP Authenticator](/multifactor-authentication/api/otp)
+- [Associate OTP Authenticators](/mfa/guides/mfa-api/otp)
-## Verify with out-of-band (OOB)
+## Verify with Out-of-Band (OOB)
```http
POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET",
- "mfa_token": "MFA_TOKEN",
- "grant_type": "http://auth0.com/oauth/grant-type/mfa-oob",
- "oob_code": "OOB_CODE",
- "binding_code": "BINDING_CODE"
-}
+Content-Type: application/x-www-form-urlencoded
+
+client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&mfa_token=MFA_TOKEN&grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-oob&oob_code=OOB_CODE&binding_code=BINDING_CODE
```
```shell
curl --request POST \
--url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"mfa_token":"MFA_TOKEN", "oob_code": "OOB_CODE", "binding_code": "BINDING_CODE", "grant_type": "http://auth0.com/oauth/grant-type/mfa-oob", "client_id": "${account.clientId}", "client_secret": "YOUR_CLIENT_SECRET"}'
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&mfa_token=MFA_TOKEN&grant_type=http://auth0.com/oauth/grant-type/mfa-oob&oob_code=OOB_CODE&binding_code=BINDING_CODE'
```
```javascript
@@ -228,15 +217,15 @@ var request = require("request");
var options = { method: 'POST',
url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
{ mfa_token: 'MFA_TOKEN',
oob_code: "OOB_CODE",
binding_code: "BINDING_CODE"
grant_type: 'http://auth0.com/oauth/grant-type/mfa-oob',
client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
+ client_secret: 'YOUR_CLIENT_SECRET' }
+ };
request(options, function (error, response, body) {
if (error) throw new Error(error);
@@ -246,6 +235,7 @@ request(options, function (error, response, body) {
```
> RESPONSE SAMPLE FOR PENDING CHALLENGE:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -256,6 +246,7 @@ Content-Type: application/json
```
> RESPONSE SAMPLE FOR VERIFIED CHALLENGE:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -267,6 +258,7 @@ Content-Type: application/json
```
> RESPONSE SAMPLE FOR REJECTED CHALLENGE:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -283,51 +275,48 @@ Content-Type: application/json
"link": "#multifactor-authentication"
}) %>
-Verifies multifactor authentication (MFA) using an out-of-band (OOB) challenge (either Push notification or SMS).
+Verifies multi-factor authentication (MFA) using an out-of-band (OOB) challenge (either Push notification, SMS, or Voice).
-To verify MFA using an OOB challenge your application must make a request to `/oauth/token` with `grant_type=http://auth0.com/oauth/grant-type/mfa-oob`. Include the `oob_code` you received from the challenge response, as well as the `mfa_token` you received as part of `mfa_required` error.
+To verify MFA using an OOB challenge, your application must make a request to `/oauth/token` with `grant_type=http://auth0.com/oauth/grant-type/mfa-oob`. Include the `oob_code` you received from the challenge response, as well as the `mfa_token` you received as part of `mfa_required` error.
The response to this request depends on the status of the underlying challenge verification:
-- If the challenge has been accepted and verified: it will be the same as `password` or `http://auth0.com/oauth/grant-type/password-realm` grant types.
+- If the challenge has been accepted and verified, it will be the same as `password` or `http://auth0.com/oauth/grant-type/password-realm` grant types.
- If the challenge has been rejected, you will get an `invalid_grant` error, meaning that the challenge was rejected by the user. At this point you should stop polling, as this response is final.
-- If the challenge verification is still pending (meaning it has not been accepted nor rejected) you will get an `authorization_pending` error, meaning that you must retry the same request a few seconds later. If you request too frequently you will get a `slow_down` error.
+- If the challenge verification is still pending (meaning it has not been accepted nor rejected), you will get an `authorization_pending` error, meaning that you must retry the same request a few seconds later. If you request too frequently, you will get a `slow_down` error.
-When the challenge response includes a `binding_method: prompt` your app needs to prompt the user for the `binding_code` and send it as part of the request. The `binding_code` is a usually a 6 digit number (similar to an OTP) included as part of the challenge. No `binding_code` is necessary if the challenge response did not include a `binding_method`. In this scenario the response will be immediate; you will receive an `invalid_grant` or an `access_token` as response.
+When the challenge response includes a `binding_method: prompt`, your app needs to prompt the user for the `binding_code` and send it as part of the request. The `binding_code` is usually a 6-digit number (similar to an OTP) included as part of the challenge. No `binding_code` is necessary if the challenge response did not include a `binding_method`. In this scenario, the response will be immediate; you will receive an `invalid_grant` or an `access_token` as response.
### Request parameters
| Parameter | Description |
|:-----------------|:------------|
-| `grant_type` Required | Denotes the flow you are using. For OTP MFA use `http://auth0.com/oauth/grant-type/mfa-oob`. |
+| `grant_type` Required | Denotes the flow you are using. For OTP MFA, use `http://auth0.com/oauth/grant-type/mfa-oob`. |
| `client_id` Required | Your application's Client ID. |
-| `client_secret` | Your application's Client Secret. **Required** when the **Token Endpoint Authentication Method** field at your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings) is `Post` or `Basic`. |
+| `client_assertion`| A JWT containing a signed assertion with your application credentials. Required when Private Key JWT is your application authentication method.|
+| `client_assertion_type`| The value is `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method.|
+| `client_secret` | Your application's Client Secret. Required when the Token Endpoint Authentication Method field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. |
| `mfa_token` Required | The `mfa_token` you received from `mfa_required` error. |
| `oob_code` Required | The oob code received from the challenge request. |
| `binding_code`| 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. |
-### More informationm
+### Learn More
-- [Associate an OTP Authenticator](/multifactor-authentication/api/oob)
+- [Associate Out-of-Band Authenticators](/mfa/guides/mfa-api/oob)
-## Verify with recovery code
+## Verify with Recovery Code
```http
POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET",
- "mfa_token": "MFA_TOKEN",
- "grant_type": "http://auth0.com/oauth/grant-type/mfa-recovery-code",
- "recovery_code": "RECOVERY_CODE"
-}
+Content-Type: application/x-www-form-urlencoded
+
+client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&mfa_token=MFA_TOKEN&grant_type=http%3A%2F%2Fauth0.com%2Foauth%2Fgrant-type%2Fmfa-recovery-code&recovery_code=RECOVERY_CODE
```
```shell
curl --request POST \
--url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"mfa_token":"MFA_TOKEN", "recovery_code":"RECOVERY_CODE", "grant_type": "http://auth0.com/oauth/grant-type/mfa-recovery-code", "client_id": "${account.clientId}", "client_secret": "YOUR_CLIENT_SECRET"}'
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&mfa_token=MFA_TOKEN&grant_type=http://auth0.com/oauth/grant-type/mfa-recovery-code&recovery_code=RECOVERY_CODE'
```
```javascript
@@ -335,14 +324,14 @@ var request = require("request");
var options = { method: 'POST',
url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
{ mfa_token: 'MFA_TOKEN',
recovery_code: 'RECOVERY_CODE',
- grant_type: 'http://auth0.com/oauth/grant-type/mfa-recover-code',
+ grant_type: 'http://auth0.com/oauth/grant-type/mfa-recovery-code',
client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
+ client_secret: 'YOUR_CLIENT_SECRET' }
+ };
request(options, function (error, response, body) {
if (error) throw new Error(error);
@@ -352,6 +341,7 @@ request(options, function (error, response, body) {
```
> RESPONSE SAMPLE FOR OTP:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -370,23 +360,25 @@ Content-Type: application/json
"link": "#multifactor-authentication"
}) %>
-Verifies multifactor authentication (MFA) using a recovery code.
+Verifies multi-factor authentication (MFA) using a recovery code.
-Some multifactor authentication (MFA) providers (such as Guardian) support using a recovery code to login. Use this method to authenticate when the user's enrolled device is unavailable, or the user cannot receive the challenge or accept it due to connectivity issues.
+Some multi-factor authentication (MFA) providers (such as Guardian) support using a recovery code to login. Use this method to authenticate when the user's enrolled device is unavailable, or the user cannot receive the challenge or accept it due to connectivity issues.
-To verify MFA using a recovery code your app must prompt the user for the recovery code, and then make a request to `oauth/token` with `grant_type=http://auth0.com/oauth/grant-type/mfa-recovery-code`. Include the collected recovery code and the `mfa_token` from the `mfa_required` error. If the recovery code is accepted the response will be the same as for `password` or `http://auth0.com/oauth/grant-type/password-realm` grant types. It might also include a `recovery_code` field, which the application must display to the end-user to be stored securely for future use.
+To verify MFA using a recovery code your app must prompt the user for the recovery code, and then make a request to `oauth/token` with `grant_type=http://auth0.com/oauth/grant-type/mfa-recovery-code`. Include the collected recovery code and the `mfa_token` from the `mfa_required` error. If the recovery code is accepted, the response will be the same as for `password` or `http://auth0.com/oauth/grant-type/password-realm` grant types. It might also include a `recovery_code` field, which the application must display to the end-user to be stored securely for future use.
### Request parameters
| Parameter | Description |
|:-----------------|:------------|
-| `grant_type` Required | Denotes the flow you are using. For OTP MFA use `http://auth0.com/oauth/grant-type/mfa-otp`. |
+| `grant_type` Required | Denotes the flow you are using. For recovery code use `http://auth0.com/oauth/grant-type/mfa-recovery-code`. |
| `client_id` Required | Your application's Client ID. |
-| `client_secret` | Your application's Client Secret. **Required** when the **Token Endpoint Authentication Method** field at your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings) is `Post` or `Basic`. |
+| `client_assertion`| A JWT containing a signed assertion with your application credentials. Required when Private Key JWT is your application authentication method.|
+| `client_assertion_type`| The value is `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method.|
+| `client_secret` | Your application's Client Secret. Required when the Token Endpoint Authentication Method field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. |
| `mfa_token` Required | The `mfa_token` you received from `mfa_required` error. |
| `recovery_code` Required | Recovery code provided by the end-user.
-## Add an authenticator
+## Add an Authenticator
```http
POST https://${account.namespace}/mfa/associate
@@ -401,7 +393,6 @@ Authorization: Bearer ACCESS_TOKEN or MFA_TOKEN
}
```
-
```shell
curl --request POST \
--url 'https://${account.namespace}/mfa/associate' \
@@ -435,6 +426,7 @@ request(options, function (error, response, body) {
```
> RESPONSE SAMPLE FOR OOB (SMS channel):
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -442,12 +434,13 @@ Content-Type: application/json
"oob_code": "Fe26.2**da6....",
"binding_method":"prompt",
"authenticator_type":"oob",
- "oob_channel":"sms",
+ "oob_channels":"sms",
"recovery_codes":["ABCDEFGDRFK75ABYR7PH8TJA"],
}
```
> RESPONSE SAMPLE FOR OOB (Auth0 channel):
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -455,12 +448,13 @@ Content-Type: application/json
"oob_code": "Fe26.2**da6....",
"barcode_uri":"otpauth://...",
"authenticator_type":"oob",
- "oob_channel":"auth0",
+ "oob_channels":"auth0",
"recovery_codes":["ABCDEFGDRFK75ABYR7PH8TJA"],
}
```
> RESPONSE SAMPLE FOR OTP:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -478,39 +472,37 @@ Content-Type: application/json
"link": "#multifactor-authentication"
}) %>
-::: warning
-This endpoint is still under development. It is available to customers with early access.
-:::
+Associates or adds a new authenticator for multi-factor authentication (MFA).
-Associates or adds a new authenticator for multifactor authentication.
+If the user has active authenticators, an Access Token with the `enroll` scope and the `audience` set to `https://${account.namespace}/mfa/` is required to use this endpoint.
-If the user has active authenticators, an [Access Token](/tokens/access-token) with the `enroll` scope and the `audience` set to `https://${account.namespace}/mfa` is required to use this endpoint.
+If the user has no active authenticators, you can use the `mfa_token` from the `mfa_required` error in place of an Access Token for this request.
-If the user has no active authenticators, you can use the `mfa_token` from the `mfa_required` error in place of an [Access Token](/tokens/access-token) for this request.
+After an authenticator is added, it must be verified. To verify the authenticator, use the response values from the `/mfa/associate` request in place of the values returned from the `/mfa/challenge` endpoint and continue with the verification flow.
-After an authenticator is added it must be verified. To verify the authenticator, use the response values from the `/mfa/associate` request in place of the values returned from the `/mfa/challenge` endpoint and continue with the verification flow.
+A `recovery_codes` field is included in the response the first time an authenticator is added. You can use `recovery_codes` to pass multi-factor authentication as shown on [Verify with recovery code](#verify-with-recovery-code) above.
-A `recovery_codes` field is included in the response the first time an authenticator is added. You can use `recovery_codes` to pass multifactor authentication as shown on [Verify with recovery code](#verify-with-recovery-code) above.
-
-To access this endoint you must set an [Access Token](/tokens/access-token) at the Authorization header, with the following claims:
+To access this endpoint, you must set an Access Token at the Authorization header, with the following claims:
- `scope`: `enroll`
-- `audience`: `https://${account.namespace}/mfa`
+- `audience`: `https://${account.namespace}/mfa/`
### Request parameters
| Parameter | Description |
|:-----------------|:------------|
| `client_id` Required | Your application's Client ID. |
-| `client_secret` | Your application's Client Secret. **Required** when the **Token Endpoint Authentication Method** field in your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings) is `Post` or `Basic`. |
+| `client_assertion`| A JWT containing a signed assertion with your application credentials. Required when Private Key JWT is your application authentication method.|
+| `client_assertion_type`| The value is `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method.|
+| `client_secret` | Your application's Client Secret. Required when the Token Endpoint Authentication Method field in your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. |
| `authenticator_types` Required | The type of authenticators supported by the client. Value is an array with values `"otp"` or `"oob"`. |
-| `oob_channel` | The type of OOB channels supported by the client. An array with values `"auth0"` or `"sms"`. Required if `authenticator_types` include `oob`. |
-| `phone_number` | The phone number to use for SMS. Required if `oob_channel` includes `sms`. |
+| `oob_channels` | The type of OOB channels supported by the client. An array with values `"auth0"`, `"sms"`, `"voice"`. Required if `authenticator_types` include `oob`. |
+| `phone_number` | The phone number to use for SMS or Voice. Required if `oob_channels` includes `sms` or `voice`. |
-### More information
+### Learn More
-- [Associate a New Authenticator for Use with Multifactor Authentication](/multifactor-authentication/api)
+- [Multi-factor Authentication API](/mfa/concepts/mfa-api)
-## List authenticators
+## List Authenticators
```http
GET https://${account.namespace}/mfa/authenticators
@@ -544,6 +536,7 @@ request(options, function (error, response, body) {
```
> RESPONSE SAMPLE:
+
```JSON
HTTP/1.1 200 OK
Content-Type: application/json
@@ -556,21 +549,21 @@ Content-Type: application/json
{
"id":"sms|dev_gB342kcL2K22S4yB",
"authenticator_type":"oob",
- "oob_channel":"sms",
+ "oob_channels":"sms",
"name":"+X XXXX1234",
"active":true
},
{
"id":"sms|dev_gB342kcL2K22S4yB",
"authenticator_type":"oob",
- "oob_channel":"sms",
+ "oob_channels":"sms",
"name":"+X XXXX1234",
"active":false
},
{
"id":"push|dev_433sJ7Mcwj9P794y",
"authenticator_type":"oob",
- "oob_channel":"auth0",
+ "oob_channels":"auth0",
"name":"John's Device",
"active":true
},
@@ -581,6 +574,7 @@ Content-Type: application/json
}
]
```
+
<%= include('../../_includes/_http-method', {
"http_badge": "badge-primary",
"http_method": "GET",
@@ -588,28 +582,24 @@ Content-Type: application/json
"link": "#multifactor-authentication"
}) %>
-::: warning
-This endpoint is still under development. It is available to customers with early access.
-:::
-
Returns a list of authenticators associated with your application.
-To access this endoint you must set an [Access Token](/tokens/access-token) at the Authorization header, with the following claims:
+To access this endpoint you must set an Access Token at the Authorization header, with the following claims:
- `scope`: `read:authenticators`
-- `audience`: `https://${account.namespace}/mfa`
+- `audience`: `https://${account.namespace}/mfa/`
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `ACCESS_TOKEN` Required | The `access_token` obtained during login. |
+| `ACCESS_TOKEN` Required | The Access Token obtained during login. |
-#### More information
+#### Learn More
-- [Manage Authenticators: List Authenticators](/multifactor-authentication/api/manage#list-authenticators)
+- [Manage Authenticators](/mfa/guides/mfa-api/manage)
-## Delete an authenticator
+## Delete an Authenticator
```http
DELETE https://${account.namespace}/mfa/authenticators/AUTHENTICATOR_ID
@@ -641,6 +631,7 @@ request(options, function (error, response, body) {
```
> RESPONSE SAMPLE:
+
```JSON
HTTP/1.1 204 OK
```
@@ -651,26 +642,21 @@ HTTP/1.1 204 OK
"link": "#multifactor-authentication"
}) %>
-::: warning
-This endpoint is still under development. It is available to customers with early access.
-:::
-
Deletes an associated authenticator using its ID.
You can get authenticator IDs by [listing the authenticators](#list-authenticators).
-To access this endoint you must set an [Access Token](/tokens/access-token) at the Authorization header, with the following claims:
+To access this endpoint, you must set an Access Token at the Authorization header, with the following claims:
- `scope`: `remove:authenticators`
-- `audience`: `https://${account.namespace}/mfa`
-
+- `audience`: `https://${account.namespace}/mfa/`
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `ACCESS_TOKEN` Required | The `access_token` obtained during login. |
+| `ACCESS_TOKEN` Required | The Access Token obtained during login. |
| `AUTHENTICATOR_ID` Required | The ID of the authenticator to delete.
-### More information
+### Learn More
-- [Manage Authenticators: Delete Authenticators](/multifactor-authentication/api/manage#delete-authenticators)
+- [Manage Authenticators](/mfa/guides/mfa-api/manage)
diff --git a/articles/api/authentication/_passwordless.md b/articles/api/authentication/_passwordless.md
index 76f89ac175..4cb6994684 100644
--- a/articles/api/authentication/_passwordless.md
+++ b/articles/api/authentication/_passwordless.md
@@ -2,7 +2,7 @@
# Passwordless
-Passwordless connections do not require the user to remember a password. Instead, another mechanism is used to prove identity, such as a one-time code sent through email or SMS, every time the user logs in.
+Passwordless connections do not require the user to remember a password. Instead, another mechanism is used to prove identity, such as a one-time code sent through email or SMS, every time the user logs in.
## Get Code or Link
@@ -11,9 +11,10 @@ POST https://${account.namespace}/passwordless/start
Content-Type: application/json
{
"client_id": "${account.clientId}",
+ "client_secret": "YOUR_CLIENT_SECRET", // for web applications
"connection": "email|sms",
- "email": "EMAIL", //set for connection=email
- "phone_number": "PHONE_NUMBER", //set for connection=sms
+ "email": "USER_EMAIL", //set for connection=email
+ "phone_number": "USER_PHONE_NUMBER", //set for connection=sms
"send": "link|code", //if left null defaults to link
"authParams": { // any authentication parameters that you would like to add
"scope": "openid",
@@ -26,7 +27,7 @@ Content-Type: application/json
curl --request POST \
--url 'https://${account.namespace}/passwordless/start' \
--header 'content-type: application/json' \
- --data '{"client_id":"${account.clientId}", "connection":"email|sms", "email":"EMAIL", "phone_number":"PHONE_NUMBER", "send":"link|code", "authParams":{"scope": "openid","state": "YOUR_STATE"}}'
+ --data '{"client_id":"${account.clientId}", "connection":"email|sms", "email":"USER_EMAIL", "phone_number":"USER_PHONE_NUMBER", "send":"link|code", "authParams":{"scope": "openid","state": "YOUR_STATE"}}'
```
```javascript
@@ -89,54 +90,54 @@ You have three options for [passwordless authentication](/connections/passwordle
| Parameter | Description |
|:-----------------|:------------|
| `client_id` Required | The `client_id` of your application. |
+| `client_assertion` | A JWT containing containing a signed assertion with your applications credentials. Required when Private Key JWT is your application authentication method. |
+|`client_assertion_type`| Use the value `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method.|
+| `client_secret` | The `client_secret` of your application. Required when the Token Endpoint Authentication Method field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. Specifically required for Regular Web Applications **only**. |
| `connection` Required | How to send the code/link to the user. Use `email` to send the code/link using email, or `sms` to use SMS. |
| `email` | Set this to the user's email address, when `connection=email`. |
| `phone_number` | Set this to the user's phone number, when `connection=sms`. |
| `send` | Use `link` to send a link or `code` to send a verification code. If null, a link will be sent. |
| `authParams` | Use this to append or override the link parameters (like `scope`, `redirect_uri`, `protocol`, `response_type`), when you send a link using email. |
-### Test with Postman
-
-<%= include('../../_includes/_test-with-postman') %>
### Remarks
-- If you sent a verification code, using either email or SMS, after you get the code, you have to authenticate the user using the [/oauth/ro endpoint](#authenticate-user), using `email` or `phone_number` as the `username`, and the verification code as the `password`.
-- This endpoint is designed to be called from the client-side, and has a [rate limit](/policies/rate-limits#authentication-api) of 50 requests per hour per IP.
+- If you sent a verification code, using either email or SMS, after you get the code, you have to authenticate the user using the [/passwordless/verify endpoint](#authenticate-user), using `email` or `phone_number` as the `username`, and the verification code as the `password`.
+- This endpoint is designed to be called from the client-side, and is subject to [rate limits](/policies/rate-limit-policy/authentication-api-endpoint-rate-limits).
- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
### Error Codes
For the complete error code reference for this endpoint refer to [Errors > POST /passwordless/start](#post-passwordless-start).
-### More Information
+### Learn More
- [Passwordless Authentication](/connections/passwordless)
-- [Authenticate users with using Passwordless Authentication via Email](/connections/passwordless/email)
-- [Authenticate users with a one-time code via SMS](/connections/passwordless/sms)
-- [Authenticate users with Touch ID](/connections/passwordless/ios-touch-id-swift)
-- [Passwordless FAQ](/connections/passwordless/faq)
+- [Passwordless Best Practices](/connections/passwordless/best-practices)
## Authenticate User
```http
-POST https://${account.namespace}/oauth/ro
+POST https://${account.namespace}/oauth/token
Content-Type: application/json
{
+ "grant_type" : "http://auth0.com/oauth/grant-type/passwordless/otp",
"client_id": "${account.clientId}",
- "connection": "email|sms",
- "grant_type": "password",
- "username": "EMAIL|PHONE", //email or phone number
- "password": "VERIFICATION_CODE", //the verification code
- "scope": "SCOPE"
+ "client_secret": "YOUR_CLIENT_SECRET", // for web applications
+ "otp": "CODE",
+ "realm": "email|sms" //email or sms
+ "username":"USER_EMAIL|USER_PHONE_NUMBER", // depends on which realm you chose
+ "audience" : "API_IDENTIFIER", // in case you need an access token for a specific API
+ "scope": "SCOPE",
+ "redirect_uri": "REDIRECT_URI"
}
```
```shell
curl --request POST \
- --url 'https://${account.namespace}/oauth/ro' \
+ --url 'https://${account.namespace}/oauth/token' \
--header 'content-type: application/json' \
- --data '{"client_id":"${account.clientId}", "connection":"email|sms", "grant_type":"password", "username":"EMAIL|PHONE", "password":"VERIFICATION_CODE", "scope":"SCOPE"}'
+ --data '{"grant_type":"http://auth0.com/oauth/grant-type/passwordless/otp", "client_id":"${account.clientId}", "client_secret":"CLIENT_SECRET", "otp":"CODE", "realm":"email|sms", "username":"USER_EMAIL|USER_PHONE_NUMBER", "audience":"API_IDENTIFIER", "scope":"SCOPE", "redirect_uri": "REDIRECT_URI"}'
```
```javascript
@@ -184,55 +185,72 @@ curl --request POST \
<%= include('../../_includes/_http-method', {
"http_badge": "badge-success",
"http_method": "POST",
- "path": "/oauth/ro",
+ "path": "/oauth/token",
"link": "#authenticate-user"
}) %>
-::: warning
-This feature is disabled by default for new tenants as of 8 June 2017. Please see [Application Grant Types](/applications/application-grant-types) for more information.
-:::
-Once you have a verification code, use this endpoint to login the user with their phone number/email and verification code. This is active authentication, so the user must enter the code in your app.
+Once you have a verification code, use this endpoint to login the user with their phone number/email and verification code.
### Request Parameters
| Parameter |Description |
|:-----------------|:------------|
+| `grant_type` Required | It should be `http://auth0.com/oauth/grant-type/passwordless/otp`. |
| `client_id` Required | The `client_id` of your application. |
-| `connection` Required | Use `sms` or `email` (should be the same as [POST /passwordless/start](#get-code-or-link)) |
-| `grant_type` Required | Use `password` |
-| `username` Required | The user's phone number if `connection=sms`, or the user's email if `connection=email`. |
-| `password` Required | The user's verification code. |
-| `scope` | Use `openid` to get an `id_token`, or `openid profile email` to include also user profile information in the `id_token`. |
+| `client_assertion`| A JWT containing a signed assertion with your application credentials. Required when Private Key JWT is your application authentication method.|
+| `client_assertion_type`| The value is `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method.|
+| `client_secret` | The `client_secret` of your application. Required** when the Token Endpoint Authentication Method field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. Specifically required for Regular Web Applications **only**. |
+| `username` Required | The user's phone number if `realm=sms`, or the user's email if `realm=email`. |
+| `realm` Required | Use `sms` or `email` (should be the same as [POST /passwordless/start](#get-code-or-link)) |
+| `otp` Required | The user's verification code. |
+| `audience` | API Identifier of the API for which you want to get an Access Token. |
+| `scope` | Use `openid` to get an ID Token, or `openid profile email` to also include user profile information in the ID Token. |
+| `redirect_uri` Required | A callback URL that has been registered with your application's **Allowed Callback URLs**. |
+
+### Error Codes
-### Test with Postman
+For the complete error code reference for this endpoint refer to [Standard Error Responses](#standard-error-responses).
-<%= include('../../_includes/_test-with-postman') %>
+### Learn More
-### Test with Authentication API Debugger
+- [Passwordless Authentication](/connections/passwordless)
+
+<%= include('../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/passwordless/verify",
+ "link": "#authenticate-user-legacy"
+}) %>
-<%= include('../../_includes/_test-this-endpoint') %>
+::: warning
+This feature is disabled by default for new tenants as of 8 June 2017. Please see [Application Grant Types](/applications/concepts/application-grant-types) for more information.
+:::
-1. At the *Configuration* tab, set the fields **Application** (select the application you want to use for the test) and **Connection** (use `sms` or `email`).
+Once you have a verification code, use this endpoint to login the user with their phone number/email and verification code. This is active authentication, so the user must enter the code in your app.
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
+### Request Parameters
-1. At the *OAuth2 / OIDC* tab, set **Username** to the user's phone number if `connection=sms`, or the user's email if `connection=email`, and **Password** to the user's verification code. Click **Resource Owner Endpoint**.
+| Parameter |Description |
+|:-----------------|:------------|
+| `client_id` Required | The `client_id` of your application. |
+| `connection` Required | Use `sms` or `email` (should be the same as [POST /passwordless/start](#get-code-or-link)) |
+| `grant_type` Required | Use `password` |
+| `username` Required | The user's phone number if `connection=sms`, or the user's email if `connection=email`. |
+| `password` Required | The user's verification code. |
+| `scope` | Use `openid` to get an ID Token, or `openid profile email` to include also user profile information in the ID Token. |
### Remarks
-- The `profile` scope value requests access to the End-User's default profile Claims, which are: `name`, `family_name`, `given_name`, `middle_name`, `nickname`, `preferred_username`, `profile`, `picture`, `website`, `gender`, `birthdate`, `zoneinfo`, `locale`, and `updated_at`.
+- The `profile` scope value requests access to the End-User's default profile Claims, which are: `name`, `family_name`, `given_name`, `middle_name`, `nickname`, `preferred_username`, `profile`, `picture`, `website`, `gender`, `birthdate`, `zoneinfo`, `locale`, and `updated_at`.
- The `email` scope value requests access to the `email` and `email_verified` Claims.
- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
### Error Codes
-For the complete error code reference for this endpoint refer to [Errors > POST /oauth/ro](#post-oauth-ro).
+For the complete error code reference for this endpoint refer to [Errors > POST /passwordless/verify](#post-passwordless-verify).
-### More Information
+### Learn More
+
+- [Passwordless Best Practices](/connections/passwordless/best-practices)
-- [Passwordless Authentication](/connections/passwordless)
-- [Authenticate users with using Passwordless Authentication via Email](/connections/passwordless/email)
-- [Authenticate users with a one-time code via SMS](/connections/passwordless/sms)
-- [Authenticate users with Touch ID](/connections/passwordless/ios-touch-id-swift)
-- [Passwordless FAQ](/connections/passwordless/faq)
diff --git a/articles/api/authentication/_saml-sso.md b/articles/api/authentication/_saml-sso.md
index 7827d283a9..0769a51318 100644
--- a/articles/api/authentication/_saml-sso.md
+++ b/articles/api/authentication/_saml-sso.md
@@ -1,6 +1,6 @@
# SAML
-The SAML protocol is used for 3rd party SaaS applications mostly, like Salesforce and Box. Auth0 supports SP and IDP Initiated Sign On. For more information refer to: [SAML](/protocols/saml).
+The SAML protocol is used mostly for third-party SaaS applications, like Salesforce and Box. Auth0 supports Service Provider (SP) and Identity Provider (IDP) initiated Sign On. To learn more, see [SAML](/protocols/saml).
## Accept Request
@@ -25,30 +25,28 @@ include('../../_includes/_http-method', {
"link": "#accept-request"
}) %>
-Use this endpoint to accept a SAML request to initiate a login.
+Use this endpoint to accept a SAML request to initiate a login.
-Optionally, it accepts a connection parameter to login with a specific provider. If no connection is specified, the [Auth0 Login Page](/login_page) will be shown.
+Optionally, you can include a `connection` parameter to log in with a specific provider. If no connection is specified, the [Auth0 Login Page](/authenticate/login/auth0-universal-login) will be shown.
+
+Optionally, SP-initiated login requests can include an `organization` parameter to authenticate users in the context of an organization. To learn more, see [Organizations](/organizations).
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `client_id` Required | The `client_id` of your application. |
-| `connection` | The connection to use. |
-
-
-### Test with Postman
-
-<%= include('../../_includes/_test-with-postman') %>
+| `client_id` Required | Client ID of your application. |
+| `connection` | Connection to use during login. |
+| `organization` | Organization ID, if authenticating in the context of an organization. |
### Remarks
- All the parameters of the SAML response can be modified with [Rules](/rules).
-- The SAML request `AssertionConsumerServiceURL` will be used to `POST` back the assertion. It must match the application's `callback_URL`.
+- The SAML request `AssertionConsumerServiceURL` will be used to `POST` back the assertion. It must match one of the application's `callback_URLs`.
-### More Information
+### Learn More
- [SAML](/protocols/saml)
## Get Metadata
@@ -71,7 +69,7 @@ include('../../_includes/_http-method', {
"link": "#get-metadata"
}) %>
-This endpoint returns the SAML 2.0 metadata.
+This endpoint returns the SAML 2.0 metadata.
### Request Parameters
@@ -80,16 +78,11 @@ This endpoint returns the SAML 2.0 metadata.
| `client_id` Required | The `client_id` of your application. |
-### Test with Postman
-
-<%= include('../../_includes/_test-with-postman') %>
-
-
-### More Information
+### Learn More
- [SAML](/protocols/saml)
-## IdP-Initiated SSO Flow
+## IdP-Initiated Single Sign-On (SSO) Flow
```http
POST https://${account.namespace}/login/callback?connection=CONNECTION
@@ -113,7 +106,7 @@ include('../../_includes/_http-method', {
"link": "#idp-initiated-sso-flow"
}) %>
-This endpoint accepts an IdP-Initiated Sign On SAMLResponse from a SAML Identity Provider. The connection corresponding to the identity provider is specified in the querystring. The user will be redirected to the application that is specified in the SAML Provider IdP-Initiated Sign On section.
+This endpoint accepts an IdP-Initiated Sign On SAMLResponse from a SAML Identity Provider. The connection corresponding to the identity provider is specified in the query string. The user will be redirected to the application that is specified in the SAML Provider IdP-Initiated Sign On section.
### Request Parameters
@@ -123,17 +116,5 @@ This endpoint accepts an IdP-Initiated Sign On SAMLResponse from a SAML Identity
| `connection` Required | The name of an identity provider configured to your application. |
| `SAMLResponse` Required | An IdP-Initiated Sign On SAML Response. |
-
-### Test with Authentication API Debugger
-
-<%= include('../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the field **Application** (select the application you want to use for the test) and **Connection** (the name of the configured identity provider).
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *Other Flows* tab, click **SAML**.
-
-
-### More Information
+### Learn More
- [SAML](/protocols/saml)
diff --git a/articles/api/authentication/_sign-up.md b/articles/api/authentication/_sign-up.md
index c00be0399f..46e637c7bd 100644
--- a/articles/api/authentication/_sign-up.md
+++ b/articles/api/authentication/_sign-up.md
@@ -1,4 +1,5 @@
# Signup
+
```http
POST https://${account.namespace}/dbconnections/signup
@@ -8,6 +9,12 @@ Content-Type: application/json
"email": "EMAIL",
"password": "PASSWORD",
"connection": "CONNECTION",
+ "username": "johndoe",
+ "given_name": "John",
+ "family_name": "Doe",
+ "name": "John Doe",
+ "nickname": "johnny",
+ "picture": "http://example.org/jdoe.png"
"user_metadata": { plan: 'silver', team_id: 'a111' }
}
```
@@ -16,7 +23,7 @@ Content-Type: application/json
curl --request POST \
--url 'https://${account.namespace}/dbconnections/signup' \
--header 'content-type: application/json' \
- --data '{"client_id":"${account.clientId}", "email":"test.account@signup.com", "password":"PASSWORD", "connection":"CONNECTION", "user_metadata":{ "plan": "silver", "team_id": "a111" }}'
+ --data '{"client_id":"${account.clientId}", "email":"test.account@signup.com", "password":"PASSWORD", "connection":"CONNECTION", "username": "johndoe", "given_name": "John", "family_name": "Doe", "name": "John Doe", "nickname": "johnny", "picture": "http://example.org/jdoe.png", "user_metadata":{ "plan": "silver", "team_id": "a111" }}'
```
```javascript
@@ -33,6 +40,12 @@ curl --request POST \
connection: 'CONNECTION',
email: 'EMAIL',
password: 'PASSWORD',
+ username: "johndoe",
+ given_name: "John",
+ family_name: "Doe",
+ name: "John Doe",
+ nickname: "johnny",
+ picture: "http://example.org/jdoe.png",
user_metadata: { plan: 'silver', team_id: 'a111' }
}, function (err) {
if (err) return alert('Something went wrong: ' + err.message);
@@ -48,7 +61,12 @@ curl --request POST \
"_id": "58457fe6b27...",
"email_verified": false,
"email": "test.account@signup.com",
- "user_metadata":{"plan":"silver","team_id":"a111"}
+ "username": "johndoe",
+ "given_name": "John",
+ "family_name": "Doe",
+ "name": "John Doe",
+ "nickname": "johnny",
+ "picture": "http://example.org/jdoe.png"
}
```
@@ -59,7 +77,7 @@ curl --request POST \
"link": "#signup"
}) %>
-Given a user's credentials, and a `connection`, this endpoint will create a new user using active authentication.
+Given a user's credentials and a `connection`, this endpoint creates a new user.
This endpoint only works for database connections.
@@ -68,24 +86,26 @@ This endpoint only works for database connections.
| Parameter | Description |
|:-----------------|:------------|
-| `client_id` Required | The `client_id` of your client. |
+| `client_id` | The `client_id` of your client. |
| `email` Required | The user's email address. |
| `password` Required | The user's desired password. |
| `connection` Required | The name of the database configured to your client. |
-| `user_metadata` | The [user metadata](/metadata) to be associated with the user. If set, the field must be an object containing no more than ten properties. Property names can have a maximum of 100 characters, and property values must be strings of no more than 500 characters. |
-
-### Test with Postman
-
-<%= include('../../_includes/_test-with-postman') %>
+| `username` | The user's username. Only valid if the connection requires a username. |
+| `given_name` | The user's given name(s). |
+| `family_name` | The user's family name(s). |
+| `name` | The user's full name. |
+| `nickname` | The user's nickname. |
+| `picture` | A URI pointing to the user's picture. |
+| `user_metadata` | The [user metadata](/users/concepts/overview-user-metadata) to be associated with the user. If set, the field must be an object containing no more than ten properties. Property names can have a maximum of 100 characters, and property values must be strings of no more than 500 characters. |
### Remarks
- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
-### More Information
+### Learn More
- [Password Strength in Auth0 Database Connections](/connections/database/password-strength)
- [Password Options in Auth0 Database Connections](/connections/database/password-options)
- [Adding Username for Database Connections](/connections/database/require-username)
-- [User Metadata](/metadata)
+- [Metadata Overview](/users/concepts/overview-user-metadata)
diff --git a/articles/api/authentication/_userinfo.md b/articles/api/authentication/_userinfo.md
index f1c01d36ac..f21daa73ff 100644
--- a/articles/api/authentication/_userinfo.md
+++ b/articles/api/authentication/_userinfo.md
@@ -1,5 +1,4 @@
# User Profile
-
## Get User Info
```http
@@ -23,15 +22,15 @@ curl --request GET \
domain: '${account.namespace}',
clientID: '${account.clientId}'
});
-
- // Parse the URL and extract the access_token
+
+ // Parse the URL and extract the Access Token
webAuth.parseHash(window.location.hash, function(err, authResult) {
if (err) {
return console.log(err);
}
webAuth.client.userInfo(authResult.accessToken, function(err, user) {
- // This method will make a request to the /userinfo endpoint
- // and return the user object, which contains the user's information,
+ // This method will make a request to the /userinfo endpoint
+ // and return the user object, which contains the user's information,
// similar to the response below.
});
});
@@ -42,15 +41,28 @@ curl --request GET \
```json
{
- "email_verified": false,
- "email": "test.account@userinfo.com",
- "updated_at": "2016-12-05T15:15:40.545Z",
- "name": "test.account@userinfo.com",
- "picture": "https://s.gravatar.com/avatar/dummy.png",
- "user_id": "auth0|58454...",
- "nickname": "test.account",
- "created_at": "2016-12-05T11:16:59.640Z",
- "sub": "auth0|58454..."
+ "sub": "248289761001",
+ "name": "Jane Josephine Doe",
+ "given_name": "Jane",
+ "family_name": "Doe",
+ "middle_name": "Josephine",
+ "nickname": "JJ",
+ "preferred_username": "j.doe",
+ "profile": "http://exampleco.com/janedoe",
+ "picture": "http://exampleco.com/janedoe/me.jpg",
+ "website": "http://exampleco.com",
+ "email": "janedoe@exampleco.com",
+ "email_verified": true,
+ "gender": "female",
+ "birthdate": "1972-03-31",
+ "zoneinfo": "America/Los_Angeles",
+ "locale": "en-US",
+ "phone_number": "+1 (111) 222-3434",
+ "phone_number_verified": false,
+ "address": {
+ "country": "us"
+ },
+ "updated_at": "1556845729"
}
```
@@ -61,36 +73,33 @@ curl --request GET \
"link": "#get-user-info"
}) %>
-Given the Auth0 [Access Token](/tokens/access-token) obtained during login, this endpoint returns a user's profile.
+Given the Auth0 Access Token obtained during login, this endpoint returns a user's profile.
-This endpoint will work only if `openid` was granted as a scope for the `access_token`.
+This endpoint will work only if `openid` was granted as a scope for the Access Token. The user profile information included in the response depends on the scopes requested. For example, a scope of just `openid` may return less information than a scope of `openid profile email`.
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `access_token` Required | The Auth0 `access_token` obtained during login. |
-
-### Test with Postman
+| `access_token` Required | The Auth0 Access Token obtained during login. |
-<%= include('../../_includes/_test-with-postman') %>
### Remarks
- The sample auth0.js script uses the library version 8. If you are using auth0.js version 7, please see this [reference guide](/libraries/auth0js/v7).
-- The auth0.js `parseHash` method, requires that your tokens are signed with `RS256`, rather than `HS256`. For more information about this, check the [Auth0.js v8 Migration Guide](/libraries/auth0js/migration-guide#the-parsehash-method).
-- If you want this endpoint to return `user_metadata` or other custom information, you can use [rules](/rules#copy-user-metadata-to-id-token). For more information refer to [User profile claims and scope](/api-auth/tutorials/adoption/scope-custom-claims).
+- The auth0.js `parseHash` method, requires that your tokens are signed with `RS256`, rather than `HS256`.
+- To return `user_metadata` or other custom information from this endpoint, add a custom claim to the ID token with an [Action](/secure/tokens/json-web-tokens/create-custom-claims#create-custom-claims). For more information refer to [User profile claims and scope](/api-auth/tutorials/adoption/scope-custom-claims).
- This endpoint will return three HTTP Response Headers, that provide relevant data on its rate limits:
- `X-RateLimit-Limit`: Number of requests allowed per minute.
- `X-RateLimit-Remaining`: Number of requests available. Each new request reduces this number by 1. For each minute that passes, requests are added back, so this number increases by 1 each time.
- `X-RateLimit-Reset`: Remaining time until the rate limit (`X-RateLimit-Limit`) resets. The value is in [UTC epoch seconds](https://en.wikipedia.org/wiki/Unix_time).
- The `Email` claim returns a snapshot of the email at the time of login
- Standard claims (other than `email`) return the latest value (unless the value comes from an external IdP)
-- Custom claims return a snapshot of the value at the time of login
+- Custom claims always returns the latest value of the claim
- To access the most up-to-date values for the `email` or custom claims, you must get new tokens. You can log in using silent authentication (where the `prompt` parameter for your call to the [`authorize` endpoint](/api/authentication#authorization-code-grant) equals `none`)
- To access the most up-to-date values for standard claims that were changed using an external IdP (for example, the user changed their email address in Facebook)., you must get new tokens. Log in again using the external IdP, but *not* with silent authentication.
-### More Information
+### Learn More
- [Auth0.js v8 Reference: Extract the authResult and get user info](/libraries/auth0js#extract-the-authresult-and-get-user-info)
diff --git a/articles/api/authentication/_wsfed-req.md b/articles/api/authentication/_wsfed-req.md
index 3b22830e29..c8e94025b2 100644
--- a/articles/api/authentication/_wsfed-req.md
+++ b/articles/api/authentication/_wsfed-req.md
@@ -1,5 +1,4 @@
# WS-Federation
-
## Accept Request
```http
@@ -30,24 +29,7 @@ This endpoint accepts a WS-Federation request to initiate a login.
| `wtrealm` | Can be used in place of `client-id`. |
| `whr` | The name of the connection (used to skip the login page). |
| `wctx` | Your application's state. |
-| `wreply` | The callback URL. |
-
-
-### Test with Postman
-
-<%= include('../../_includes/_test-with-postman') %>
-
-
-### Test with Authentication API Debugger
-
-<%= include('../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the field **Application** (select the application you want to use for the test) and **Connection** (the name of the configured identity provider).
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *Other Flows* tab, click **WS-Federation**.
-
+| `wreply` | The callback URL. |
### Remarks
@@ -56,23 +38,21 @@ This endpoint accepts a WS-Federation request to initiate a login.
- If this parameter does not begin with a urn, the `client.clientAliases` array is used for look-up. This can only be set with the [/api/v2/clients](/api/management/v2#!/Clients/get_clients) Management API.
- The `whr` parameter is mapped to the connection like this: `urn:CONNECTION_NAME`. For example, `urn:google-oauth2` indicates login with Google. If there is no `whr` parameter included, the user will be directed to the [Auth0 Login Page](/login_page).
-
-### More Information
+### Learn More
- [WS-Federation](/protocols/ws-fed)
-
## Get Metadata
```http
-GET https://${account.namespace}/wsfed/${account.clientId}/FederationMetadata/2007-06/FederationMetadata.xml
+GET https://${account.namespace}/wsfed/FederationMetadata/2007-06/FederationMetadata.xml
```
```shell
curl --request GET \
- --url 'https://${account.namespace}/wsfed/${account.clientId}/FederationMetadata/2007-06/FederationMetadata.xml'
+ --url 'https://${account.namespace}/wsfed/FederationMetadata/2007-06/FederationMetadata.xml'
```
-<% var getMetadataPath = '/wsfed/YOUR_CLIENT_ID/FederationMetadata/2007-06/FederationMetadata.xml'; %>
+<% var getMetadataPath = '/wsfed/FederationMetadata/2007-06/FederationMetadata.xml'; %>
<%=
include('../../_includes/_http-method', {
"http_badge": "badge-primary",
@@ -83,12 +63,6 @@ include('../../_includes/_http-method', {
This endpoint returns the WS-Federation metadata.
-
-### Test with Postman
-
-<%= include('../../_includes/_test-with-postman') %>
-
-
-### More Information
+### Learn More
- [WS-Federation](/protocols/ws-fed)
diff --git a/articles/api/authentication/api-authz/_auth-code-flow.md b/articles/api/authentication/api-authz/_auth-code-flow.md
new file mode 100644
index 0000000000..2a3e3d4f27
--- /dev/null
+++ b/articles/api/authentication/api-authz/_auth-code-flow.md
@@ -0,0 +1,120 @@
+# Authorization Code Flow
+## Authorize
+
+```http
+GET https://${account.namespace}/authorize?
+ audience=API_IDENTIFIER&
+ scope=SCOPE&
+ response_type=code&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ state=STATE
+```
+
+> RESPONSE SAMPLE
+
+```text
+HTTP/1.1 302 Found
+Location: ${account.callback}?code=AUTHORIZATION_CODE&state=STATE
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "GET",
+ "path": "/authorize",
+ "link": "#authorization-code-grant"
+}) %>
+
+This is the OAuth 2.0 grant that regular web apps utilize in order to access an API.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `audience` | The unique identifier of the target API you want to access. |
+| `scope` | The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token. |
+| `response_type` Required | Indicates to Auth0 which OAuth 2.0 flow you want to use. Use `code` for Authorization Code Grant Flow. |
+| `client_id` Required | Your application's ID. |
+| `state` Recommended | An opaque value the application adds to the initial request that Auth0 includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks. |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
+| `connection` | The name of the connection configured to your application. |
+| `prompt` | To initiate a [silent authentication](/api-auth/tutorials/silent-authentication) request, use `prompt=none` (To learn more, read the Remarks). |
+| `organization` | ID of the [organization](/organizations) to use when authenticating a user. When not provided, if your application is configured to **Display Organization Prompt**, the user will be able to enter the organization name when authenticating. |
+| `invitation` | Ticket ID of the organization invitation. When [inviting a member to an Organization](/organizations/invite-members), your application should handle invitation acceptance by forwarding the invitation and organization key-value pairs when the user accepts the invitation. |
+
+## Get Token
+
+```http
+POST https://${account.namespace}/oauth/token
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=authorization_code&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&code=AUTHORIZATION_CODE&redirect_uri=${account.callback}
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/token' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'grant_type=authorization_code&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&code=AUTHORIZATION_CODE&redirect_uri=${account.callback}'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/token',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
+ { grant_type: 'authorization_code',
+ client_id: '${account.clientId}',
+ client_secret: 'YOUR_CLIENT_SECRET',
+ code: 'AUTHORIZATION_CODE',
+ redirect_uri: '${account.callback}' }
+ };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "access_token":"eyJz93a...k4laUWw",
+ "refresh_token":"GEbRxBN...edjnXbL",
+ "id_token":"eyJ0XAi...4faeEoQ",
+ "token_type":"Bearer",
+ "expires_in":86400
+}
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#authorization-code"
+}) %>
+
+This is the flow that regular web apps use to access an API. Use this endpoint to exchange an Authorization Code for a token.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `grant_type` Required | Denotes the flow you are using. For Authorization Code, use `authorization_code`. |
+| `client_id` Required | Your application's Client ID. |
+| `client_secret` Required | Your application's Client Secret. |
+| `code` Required | The Authorization Code received from the initial `/authorize` call. |
+| `redirect_uri`| This is required only if it was set at the [GET /authorize](#authorization-code-grant) endpoint. The values from `/authorize` must match the value you set at `/oauth/token`. |
+
+### Learn More
+
+- [Authorization Code Flow](/flows/concepts/auth-code)
+- [Call API Using the Authorization Code Flow](/flows/guides/auth-code/call-api-auth-code)
+- [State Parameter](/protocols/oauth2/oauth-state)
+- [Silent Authentication](/api-auth/tutorials/silent-authentication)
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_auth-code-pkce.md b/articles/api/authentication/api-authz/_auth-code-pkce.md
new file mode 100644
index 0000000000..23edc9a190
--- /dev/null
+++ b/articles/api/authentication/api-authz/_auth-code-pkce.md
@@ -0,0 +1,126 @@
+# Authorization Code Flow with PKCE
+## Authorize
+
+```http
+GET https://${account.namespace}/authorize?
+ audience=API_IDENTIFIER&
+ scope=SCOPE&
+ response_type=code&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256
+```
+
+> RESPONSE SAMPLE
+
+```text
+HTTP/1.1 302 Found
+Location: ${account.callback}?code=AUTHORIZATION_CODE
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "GET",
+ "path": "/authorize",
+ "link": "#authorization-code-grant-pkce-"
+}) %>
+
+This is the OAuth 2.0 grant that mobile apps utilize in order to access an API. Before starting with this flow, you need to generate and store a `code_verifier`, and using that, generate a `code_challenge` that will be sent in the authorization request.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `audience` | The unique identifier of the target API you want to access. |
+| `scope` | The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token. |
+| `response_type` Required | Indicates to Auth0 which OAuth 2.0 Flow you want to perform. Use `code` for Authorization Code Grant (PKCE) Flow. |
+| `client_id` Required | Your application's Client ID. |
+| `state` Recommended | An opaque value the client adds to the initial request that Auth0 includes when redirecting back to the client. This value must be used by the client to prevent CSRF attacks. |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
+| `code_challenge_method` Required | Method used to generate the challenge. The PKCE spec defines two methods, `S256` and `plain`, however, Auth0 supports only `S256` since the latter is discouraged. |
+| `code_challenge` Required | Generated challenge from the `code_verifier`. |
+| `connection` | The name of the connection configured to your application. |
+| `prompt` | To initiate a [silent authentication](/api-auth/tutorials/silent-authentication) request, use `prompt=none` (To learn more, read the Remarks). |
+| `organization` | ID of the [organization](/organizations) to use when authenticating a user. When not provided, if your application is configured to **Display Organization Prompt**, the user will be able to enter the organization name when authenticating. |
+| `invitation` | Ticket ID of the organization invitation. When [inviting a member to an Organization](/organizations/invite-members), your application should handle invitation acceptance by forwarding the invitation and organization key-value pairs when the user accepts the invitation. |
+
+## Get Token
+```http
+POST https://${account.namespace}/oauth/token
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=authorization_code&client_id=${account.clientId}&code_verifier=CODE_VERIFIER&code=AUTHORIZATION_CODE&redirect_uri=${account.callback}
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/token' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'grant_type=authorization_code&client_id=${account.clientId}&code_verifier=CODE_VERIFIER&code=AUTHORIZATION_CODE&redirect_uri=${account.callback}'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/token',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form: {
+ grant_type:"authorization_code",
+ client_id: "${account.clientId}",
+ code_verifier: "CODE_VERIFIER",
+ code: "AUTHORIZATION_CODE",
+ redirect_uri: "${account.callback}", } };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "access_token":"eyJz93a...k4laUWw",
+ "refresh_token":"GEbRxBN...edjnXbL",
+ "id_token":"eyJ0XAi...4faeEoQ",
+ "token_type":"Bearer",
+ "expires_in":86400
+}
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#authorization-code-pkce-"
+}) %>
+
+This is the flow that mobile apps use to access an API. Use this endpoint to exchange an Authorization Code for a token.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `grant_type` Required | Denotes the flow you are using. For Authorization Code (PKCE) use `authorization_code`. |
+| `client_id` Required | Your application's Client ID. |
+| `code` Required | The Authorization Code received from the initial `/authorize` call. |
+| `code_verifier` Required | Cryptographically random key that was used to generate the `code_challenge` passed to `/authorize`. |
+| `redirect_uri` | This is required only if it was set at the [GET /authorize](#authorization-code-grant-pkce-) endpoint. The values from `/authorize` must match the value you set at `/oauth/token`. |
+
+### Remarks
+
+- In order to improve compatibility for applications, Auth0 will now return profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID tokens or access tokens, they must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims.
+- Include `offline_access` to the `scope` request parameter to get a refresh token from [POST /oauth/token](#authorization-code-pkce-). Make sure that the **Allow Offline Access** field is enabled in the [API Settings](${manage_url}/#/apis).
+- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications).
+- Silent authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page. When an Access Token has expired, silent authentication can be used to retrieve a new one without user interaction, assuming the user's Single Sign-on (SSO) session has not expired.
+
+### Learn More
+- [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce)
+- [Call API Using the Authorization Code Flow with PKCE](/flows/guides/auth-code-pkce/call-api-auth-code-pkce)
+- [Silent Authentication](/api-auth/tutorials/silent-authentication)
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_authz-client.md b/articles/api/authentication/api-authz/_authz-client.md
index 6ea3ca39f9..4979eff892 100644
--- a/articles/api/authentication/api-authz/_authz-client.md
+++ b/articles/api/authentication/api-authz/_authz-client.md
@@ -2,227 +2,24 @@
To begin an OAuth 2.0 Authorization flow, your application should first send the user to the authorization URL.
-The purpose of this call is to obtain consent from the user to invoke the API (specified in `audience`) and do certain things (specified in `scope`) on behalf of the user. Auth0 will authenticate the user and obtain consent, unless consent has been previously given. If you alter the value in `scope`, Auth0 will require consent to be given again.
+## Authorize endpoint
+The purpose of this call is to obtain consent from the user to invoke the API (specified in `audience`) and do certain things (specified in `scope`) on behalf of the user. Auth0 will authenticate the user and obtain consent, unless consent has been previously given. If you alter the value in `scope`, Auth0 will require consent to be given again.
The OAuth 2.0 flows that require user authorization are:
-- [Authorization Code Grant](/api-auth/grant/authorization-code)
-- [Authorization Code Grant using Proof Key for Code Exchange (PKCE)](/api-auth/grant/authorization-code-pkce)
-- [Implicit Grant](/api-auth/grant/implicit)
+- [Authorization Code Flow](/flows/concepts/auth-code)
+- [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce)
+- [Implicit Flow](/flows/concepts/implicit)
-On the other hand, the [Resource Owner Password Grant](/api-auth/grant/password) and [Client Credentials](/api-auth/grant/client-credentials) flows do not use this endpoint since there is no user authorization involved. Instead they invoke directly the `POST /oauth/token` endpoint to retrieve an Access Token.
+The [Resource Owner Password Grant](/api-auth/grant/password) and [Client Credentials Flow](/flows/concepts/client-credentials) do not use this endpoint since there is no user authorization involved. Instead, they directly invoke the `POST /oauth/token` endpoint to retrieve an Access Token.
-Based on the OAuth 2.0 flow you are implementing, the parameters slightly change. To determine which flow is best suited for your case refer to: [Which OAuth 2.0 flow should I use?](/api-auth/which-oauth-flow-to-use).
+Based on the OAuth 2.0 flow you are implementing, the parameters slightly change. To determine which flow is best suited for your case, refer to: [Which OAuth 2.0 flow should I use?](/api-auth/which-oauth-flow-to-use).
-## Authorization Code Grant
+## Get Token
+For token-based authentication, use the `oauth/token` endpoint to get an access token for your application to make authenticated calls to a secure API. Optionally, you can also retrieve an ID Token and a Refresh Token. ID Tokens contains user information in the form of scopes you application can extract to provide a better user experience. Refresh Tokens allow your application to request a new access token once the current token expires without interruping the user experience. To learn more, read [ID Tokens](https://auth0.com/docs/secure/tokens/id-tokens) and [Refresh Tokens](https://auth0.com/docs/secure/tokens/refresh-tokens).
-```http
-GET https://${account.namespace}/authorize?
- audience=API_IDENTIFIER&
- scope=SCOPE&
- response_type=code&
- client_id=${account.clientId}&
- redirect_uri=${account.callback}&
- state=STATE
-```
-
-> RESPONSE SAMPLE
-
-```text
-HTTP/1.1 302 Found
-Location: ${account.callback}?code=AUTHORIZATION_CODE&state=STATE
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-primary",
- "http_method": "GET",
- "path": "/authorize",
- "link": "#authorization-code-grant"
-}) %>
-
-This is the OAuth 2.0 grant that regular web apps utilize in order to access an API.
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `audience` | The unique identifier of the target API you want to access. |
-| `scope` | The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/api-auth/tutorials/adoption/scope-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token. |
-| `response_type` Required | Indicates to Auth0 which OAuth 2.0 flow you want to perform. Use `code` for Authorization Code Grant Flow. |
-| `client_id` Required | Your application's ID. |
-| `state` Recommended | An opaque value the application adds to the initial request that Auth0 includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks. |
-| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
-| `prompt` | To initiate a [silent authentication](/api-auth/tutorials/silent-authentication) request, use `prompt=none` (see Remarks for more info). |
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Client** field to the application you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the fields **Audience** (to the unique identifier of the API you want to access), **Response Type** (set to `code`) and enable the **Audience** switch.
-
-1. Click **OAuth / OIDC Login**. Following the redirect, the URL will contain the authorization code. Note, that the code will be set at the **Authorization Code** field so you can proceed with exchanging it for an Access Token.
-
-### Remarks
-
-- In order to improve compatibility for applications, Auth0 will now return profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID Tokens or Access Tokens, they must conform to a namespaced format to avoid possible collisions with standard OIDC claims. For example, if you choose the namespace `https://foo.com/` and you want to add a custom claim named `myclaim`, you would name the claim `https://foo.com/myclaim`, instead of `myclaim`.
-- Include `offline_access` to the `scope` request parameter to get a Refresh Token from [POST /oauth/token](#authorization-code). Make sure that the **Allow Offline Access** field is enabled in the [API Settings](${manage_url}/#/apis).
-- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-- Silent authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page. When an Access Token has expired, silent authentication can be used to retrieve a new one without user interaction, assuming the user's SSO session has not expired.
-
-### More Information
-
-- [Calling APIs from Server-side Web Apps](/api-auth/grant/authorization-code)
-- [Executing an Authorization Code Grant Flow](/api-auth/tutorials/authorization-code-grant)
-- [Using the State Parameter](/protocols/oauth2/oauth-state)
-- [Silent Authentication](/api-auth/tutorials/silent-authentication)
-
-
-## Authorization Code Grant (PKCE)
-
-```http
-GET https://${account.namespace}/authorize?
- audience=API_IDENTIFIER&
- scope=SCOPE&
- response_type=code&
- client_id=${account.clientId}&
- redirect_uri=${account.callback}&
- code_challenge=CODE_CHALLENGE&
- code_challenge_method=S256
-```
-
-> RESPONSE SAMPLE
-
-```text
-HTTP/1.1 302 Found
-Location: ${account.callback}?code=AUTHORIZATION_CODE
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-primary",
- "http_method": "GET",
- "path": "/authorize",
- "link": "#authorization-code-grant-pkce-"
-}) %>
-
-This is the OAuth 2.0 grant that mobile apps utilize in order to access an API. Before starting with this flow, you need to generate and store a `code_verifier`, and using that, generate a `code_challenge` that will be sent in the authorization request.
-
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `audience` | The unique identifier of the target API you want to access. |
-| `scope` | The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must conform to a namespaced format, or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token. |
-| `response_type` Required | Indicates to Auth0 which OAuth 2.0 Flow you want to perform. Use `code` for Authorization Code Grant (PKCE) Flow. |
-| `client_id` Required | Your application's Client ID. |
-| `state` Recommended | An opaque value the clients adds to the initial request that Auth0 includes when redirecting the back to the client. This value must be used by the client to prevent CSRF attacks. |
-| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
-| `code_challenge_method` Required | Method used to generate the challenge. The PKCE spec defines two methods, `S256` and `plain`, however, Auth0 supports only `S256` since the latter is discouraged. |
-| `code_challenge` Required | Generated challenge from the `code_verifier`. |
-| `prompt` | To initiate a [silent authentication](/api-auth/tutorials/silent-authentication) request, use `prompt=none` (see Remarks for more info). |
-
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Application** field to the app you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the fields **Audience** (to the unique identifier of the API you want to access), **Response Type** (set to `code`) and enable the **Audience** and **PKCE** switches.
-
-1. Click **OAuth / OIDC Login**. Following the redirect, the URL will contain the authorization code. Note, that the code will be set at the **Authorization Code** field, and the **Code Verifier** will be automatically set as well, so you can proceed with exchanging the code for an Access Token.
-
-
-### Remarks
-
-- In order to improve compatibility for applications, Auth0 will now return profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID Tokens or Access Tokens, they must conform to a namespaced format to avoid possible collisions with standard OIDC claims. For example, if you choose the namespace `https://foo.com/` and you want to add a custom claim named `myclaim`, you would name the claim `https://foo.com/myclaim`, instead of `myclaim`.
-- Include `offline_access` to the `scope` request parameter to get a Refresh Token from [POST /oauth/token](#authorization-code-pkce-). Make sure that the **Allow Offline Access** field is enabled in the [API Settings](${manage_url}/#/apis).
-- The `redirect_uri` value must be specified as a valid callback URL under your [Client's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-- Silent authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page. When an Access Token has expired, silent authentication can be used to retrieve a new one without user interaction, assuming the user's SSO session has not expired.
-
-
-### More Information
-
-- [Calling APIs from Mobile Apps](/api-auth/grant/authorization-code-pkce)
-- [Executing an Authorization Code Grant Flow with PKCE](/api-auth/tutorials/authorization-code-grant-pkce)
-- [Silent Authentication](/api-auth/tutorials/silent-authentication)
-
-
-## Implicit Grant
-
-```http
-GET https://${account.namespace}/authorize?
- audience=API_IDENTIFIER&
- scope=SCOPE&
- response_type=token|id_token|id_token token&
- client_id=${account.clientId}&
- redirect_uri=${account.callback}&
- state=STATE&
- nonce=NONCE
-```
-
-> RESPONSE SAMPLE
-
-```text
-HTTP/1.1 302 Found
-Location: ${account.callback}#access_token=TOKEN&state=STATE&token_type=TYPE&expires_in=SECONDS
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-primary",
- "http_method": "GET",
- "path": "/authorize",
- "link": "#implicit-grant"
-}) %>
-
-This is the OAuth 2.0 grant that web apps utilize in order to access an API.
-
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `audience` | The unique identifier of the target API you want to access. |
-| `scope` | The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must conform to a namespaced format, or any scopes supported by the target API (for example, `read:contacts`). |
-| `response_type` Required | This will specify the type of token you will receive at the end of the flow. Use `token` to get only an `access_token`, `id_token` to get only an `id_token` (if you don't plan on accessing an API), or `id_token token` to get both an `id_token` and an `access_token`. |
-| `client_id` Required | Your application's ID. |
-| `state` Recommended | An opaque value the application adds to the initial request that Auth0 includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks. |
-| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
-| `nonce` Recommended | A string value which will be included in the ID Token response from Auth0, [used to prevent token replay attacks](/api-auth/tutorials/nonce). It is required for `response_type=id_token token`. |
-| `connection` | The name of the connection configured to your application. |
-| `prompt` | To initiate a [silent authentication](/api-auth/tutorials/silent-authentication) request, use `prompt=none` (see Remarks for more info). |
-
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Application** field to the app you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the fields **Audience** (to the unique identifier of the API you want to access), **Response Type** (set to `token`) and enable the **Audience** switch.
-
-1. Click **OAuth / OIDC Login**.
-
-
-### Remarks
-
-- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-- If `response_type=token`, after the user authenticates with the provider, this will redirect them to your application callback URL while passing the `access_token` in the address `location.hash`. This is used for Single Page Apps and on Native Mobile SDKs.
-- The Implicit Grant does not support the issuance of Refresh Tokens. You can use [Silent Authentication](/api-auth/tutorials/silent-authentication) instead.
-- In order to improve compatibility for applications, Auth0 will now return profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID Tokens or Access Tokens, they must conform to a namespaced format to avoid possible collisions with standard OIDC claims. For example, if you choose the namespace `https://foo.com/` and you want to add a custom claim named `myclaim`, you would name the claim `https://foo.com/myclaim`, instead of `myclaim`.
-- Silent authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page. When an Access Token has expired, silent authentication can be used to retrieve a new one without user interaction, assuming the user's SSO session has not expired.
-
-### More Information
-
-- [Calling APIs from Client-side Web Apps](/api-auth/grant/implicit)
-- [Executing the Implicit Grant Flow](/api-auth/tutorials/implicit-grant)
-- [Using the State Parameter](/protocols/oauth2/oauth-state)
-- [Mitigate replay attacks when using the Implicit Grant](/api-auth/tutorials/nonce)
-- [Silent Authentication](/api-auth/tutorials/silent-authentication)
+Note that the only OAuth 2.0 flows that can retrieve a Refresh Token are:
+- [Authorization Code Flow (Authorization Code)](/flows/concepts/auth-code)
+- [Authorization Code Flow with PKCE (Authorization Code with PKCE)](/flows/concepts/auth-code-pkce)
+- [Resource Owner Password](/api-auth/grant/password)
+- [Device Authorization Flow](/flows/concepts/device-auth)
+- Token Exchange\*
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_client-credential.md b/articles/api/authentication/api-authz/_client-credential.md
new file mode 100644
index 0000000000..3f532cd8bb
--- /dev/null
+++ b/articles/api/authentication/api-authz/_client-credential.md
@@ -0,0 +1,74 @@
+# Client Credential Flow
+## Get Token
+
+```http
+POST https://${account.namespace}/oauth/token
+Content-Type: application/x-www-form-urlencoded
+
+audience=API_IDENTIFIER&grant_type=client_credentials&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/token' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'audience=API_IDENTIFIER&grant_type=client_credentials&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/token',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
+ { client_id: '${account.clientId}',
+ client_secret: 'YOUR_CLIENT_SECRET',
+ audience: 'API_IDENTIFIER',
+ grant_type: 'client_credentials' }
+ };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "access_token":"eyJz93a...k4laUWw",
+ "token_type":"Bearer",
+ "expires_in":86400
+}
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#client-credentials"
+}) %>
+
+This is the OAuth 2.0 grant that server processes use to access an API. Use this endpoint to directly request an access token by using the application's credentials (a Client ID and a Client Secret).
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `grant_type` Required | Denotes the flow you are using. For Client Credentials use `client_credentials`. |
+| `client_id` Required | Your application's Client ID. |
+| `client_secret` Required | Your application's Client Secret. |
+| `audience` Required | The unique identifier of the target API you want to access. |
+| `organization` Optional| The organization or identifier with which you want the request to be associated. To learn more, read [Machine-to-Machine Access for Organizations](https://auth0.com/docs/manage-users/organizations/organizations-for-m2m-applications)|
+
+### Learn More
+
+- [Client Credentials Flow](/flows/concepts/client-credentials)
+- [Call API using the Client Credentials Flow](/flows/guides/client-credentials/call-api-client-credentials)
+- [Setting up a Client Grant using the Management Dashboard](/api-auth/config/using-the-auth0-dashboard)
+- [Asking for Access Tokens for a Client Credentials Grant](/api-auth/config/asking-for-access-tokens)
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_device-code.md b/articles/api/authentication/api-authz/_device-code.md
new file mode 100644
index 0000000000..11a26b9470
--- /dev/null
+++ b/articles/api/authentication/api-authz/_device-code.md
@@ -0,0 +1,186 @@
+# Device Authorization Flow
+## Authorize
+
+```http
+POST https://${account.namespace}/oauth/device/code
+Content-Type: application/x-www-form-urlencoded
+
+client_id=${account.clientId}&scope=SCOPE&audience=API_IDENTIFIER
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/device/code' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'client_id=${account.clientId}&scope=SCOPE&audience=API_IDENTIFIER'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/device/code',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
+ { client_id: '${account.clientId}',
+ scope: 'SCOPE',
+ audience: 'API_IDENTIFIER' }
+ };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "device_code":"GmRh...k9eS",
+ "user_code":"WDJB-MJHT",
+ "verification_uri":"https://${account.namespace}/device",
+ "verification_uri_complete":"https://${account.namespace}/device?user_code=WDJB-MJHT",
+ "expires_in":900, //in seconds
+ "interval":5
+}
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "POST",
+ "path": "/oauth/device/code",
+ "link": "#device-code"
+}) %>
+
+This is the flow that input-constrained devices use to access an API. Use this endpoint to get a device code. To begin the [Device Authorization Flow](/flows/concepts/device-auth), your application should first request a device code.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `audience` | The unique identifier of the target API you want to access. |
+| `scope` | The scopes for which you want to request authorization. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). Include `offline_access` to get a Refresh Token. |
+| `client_id` Required | Your application's ID. |
+
+### Response Values
+
+| Value | Description |
+|:-----------------------------|:------------|
+| `device_code` | The unique code for the device. When the user visits the `verification_uri` in their browser-based device, this code will be bound to their session. |
+| `user_code` | The code that the user should input at the `verification_uri` to authorize the device. |
+| `verification_uri` | The URL the user should visit to authorize the device. |
+| `verification_uri_complete` | The complete URL the user should visit to authorize the device. Your app can use this value to embed the `user_code` in the URL, if you so choose. |
+| `expires_in` | The lifetime (in seconds) of the `device_code` and `user_code`. |
+| `interval` | The interval (in seconds) at which the app should poll the token URL to request a token. |
+
+### Remarks
+
+- Include `offline_access` to the `scope` request parameter to get a Refresh Token from [POST /oauth/token](#device-auth). Make sure that the **Allow Offline Access** field is enabled in the [API Settings](${manage_url}/#/apis).
+
+```http
+POST https://${account.namespace}/oauth/token
+Content-Type: application/x-www-form-urlencoded
+
+client_id=${account.clientId}&device_code=YOUR_DEVICE_CODE&grant_type=urn:ietf:params:oauth:grant-type:device_code
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/token' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'client_id=${account.clientId}&device_code=YOUR_DEVICE_CODE&grant_type=urn:ietf:params:oauth:grant-type:device_code'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/token',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
+ { client_id: '${account.clientId}',
+ device_code: 'YOUR_DEVICE_CODE',
+ grant_type: 'urn:ietf:params:oauth:grant-type:device_code' }
+ };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "access_token": "eyJz93a...k4laUWw",
+ "id_token": "eyJ...0NE",
+ "refresh_token": "eyJ...MoQ",
+ "scope": "...",
+ "expires_in": 86400,
+ "token_type": "Bearer"
+}
+```
+
+```JSON
+HTTP/1.1 403 Forbidden
+Content-Type: application/json
+ {
+ // Can be retried
+ "error": "authorization_pending",
+ "error_description": "User has yet to authorize device code."
+ }
+```
+
+```JSON
+HTTP/1.1 429 Too Many Requests
+Content-Type: application/json
+ {
+ // Can be retried
+ "error": "slow_down",
+ "error_description": "You are polling faster than the specified interval of 5 seconds."
+ }
+```
+
+```JSON
+HTTP/1.1 403 Forbidden
+Content-Type: application/json
+ {
+ // Cannot be retried; transaction failed
+ "error": "access_denied|invalid_grant|...",
+ "error_description": "Failure: User cancelled the confirmation prompt or consent page; the code expired; there was an error."
+ }
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#device-auth"
+}) %>
+
+This is the OAuth 2.0 grant that input-constrained devices use to access an API. Poll this endpoint using the interval returned with your [device code](/api/authentication#get-device-code) to directly request an access token using the application's credentials (a Client ID) and a device code.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `grant_type` Required | Denotes the flow you are using. For Device Authorization, use `urn:ietf:params:oauth:grant-type:device_code`. |
+| `client_id` Required | Your application's Client ID. |
+| `device_code` Required | The device code previously returned from the [/oauth/device/code endpoint](/api/authentication#device-authorization-flow). |
+
+### Remarks
+- Because you will be polling this endpoint (using the `interval` from the initial response to determine frequency) while waiting for the user to go to the verification URL and enter their user code, you will likely receive at least one failure before receiving a successful response. See sample responses for possible responses.
+
+### Learn More
+
+- [Device Authorization Flow](/flows/concepts/device-auth)
+- [Call API using the Device Authorization Flow](/flows/guides/device-auth/call-api-device-auth)
+- [Setting up a Device Code Grant using the Management Dashboard](/api-auth/config/using-the-auth0-dashboard)
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_get-token.md b/articles/api/authentication/api-authz/_get-token.md
deleted file mode 100644
index 874f3bdd6d..0000000000
--- a/articles/api/authentication/api-authz/_get-token.md
+++ /dev/null
@@ -1,495 +0,0 @@
-# Get Token
-
-Use this endpoint to:
-- Get an `access_token` in order to call an API. You can, optionally, retrieve an `id_token` and a `refresh_token` as well.
-- Refresh your Access Token, using a Refresh Token you got during authorization.
-
-Note that the only OAuth 2.0 flows that can retrieve a Refresh Token are:
-- [Authorization Code](/api-auth/grant/authorization-code)
-- [Authorization Code with PKCE](/api-auth/grant/authorization-code-pkce)
-- [Resource Owner Password](/api-auth/grant/password)
-
-## Authorization Code
-
-```http
-POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "grant_type": "authorization_code",
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET",
- "code": "AUTHORIZATION_CODE",
- "redirect_uri": "${account.callback}"
-}
-```
-
-```shell
-curl --request POST \
- --url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"grant_type":"authorization_code","client_id": "${account.clientId}","client_secret": "YOUR_CLIENT_SECRET","code": "AUTHORIZATION_CODE","redirect_uri": "${account.callback}"}'
-```
-
-```javascript
-var request = require("request");
-
-var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { grant_type: 'authorization_code',
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET',
- code: 'AUTHORIZATION_CODE',
- redirect_uri: '${account.callback}' },
- json: true };
-
-request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- console.log(body);
-});
-```
-
-> RESPONSE SAMPLE:
-
-```JSON
-HTTP/1.1 200 OK
-Content-Type: application/json
-{
- "access_token":"eyJz93a...k4laUWw",
- "refresh_token":"GEbRxBN...edjnXbL",
- "id_token":"eyJ0XAi...4faeEoQ",
- "token_type":"Bearer",
- "expires_in":86400
-}
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": "/oauth/token",
- "link": "#authorization-code"
-}) %>
-
-This is the OAuth 2.0 grant that regular web apps utilize in order to access an API. Use this endpoint to exchange an Authorization Code for a Token.
-
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `grant_type` Required | Denotes the flow you are using. For Authorization Code use `authorization_code`. |
-| `client_id` Required | Your application's Client ID. |
-| `client_secret` Required | Your application's Client Secret. |
-| `code` Required | The Authorization Code received from the initial `/authorize` call. |
-| `redirect_uri`| This is required only if it was set at the [GET /authorize](#authorization-code-grant) endpoint. The values must match. |
-
-
-### Test with Postman
-
-<%= include('../../../_includes/_test-with-postman') %>
-
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-If you have just executed the [Authorization Code Grant](#authorization-code-grant) you should already have a code set at the **Authorization Code** field of the *OAuth2 / OIDC* tab. If so, click **OAuth2 Code Exchange**, otherwise follow the instructions.
-
-1. At the *Configuration* tab, set the **Application** field to the application you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the field **Authorization Code** to the code you retrieved from [Authorization Code Grant](#authorization-code-grant). Click **OAuth2 Code Exchange**.
-
-
-### More Information
-
-- [Calling APIs from Server-side Web Apps](/api-auth/grant/authorization-code)
-- [Executing an Authorization Code Grant Flow](/api-auth/tutorials/authorization-code-grant)
-
-
-## Authorization Code (PKCE)
-
-```http
-POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "grant_type": "authorization_code",
- "client_id": "${account.clientId}",
- "code_verifier": "CODE_VERIFIER",
- "code": "AUTHORIZATION_CODE",
- "redirect_uri": "com.myclientapp://myclientapp.com/callback"
-}
-```
-
-```shell
-curl --request POST \
- --url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"grant_type":"authorization_code","client_id": "${account.clientId}","code_verifier": "CODE_VERIFIER","code": "AUTHORIZATION_CODE","redirect_uri": "com.myclientapp://myclientapp.com/callback"}'
-```
-
-```javascript
-var request = require("request");
-
-var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body: '{"grant_type":"authorization_code","client_id": "${account.clientId}","code_verifier": "CODE_VERIFIER","code": "AUTHORIZATION_CODE","redirect_uri": "com.myclientapp://myclientapp.com/callback", }' };
-
-request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- console.log(body);
-});
-```
-
-> RESPONSE SAMPLE:
-
-```JSON
-HTTP/1.1 200 OK
-Content-Type: application/json
-{
- "access_token":"eyJz93a...k4laUWw",
- "refresh_token":"GEbRxBN...edjnXbL",
- "id_token":"eyJ0XAi...4faeEoQ",
- "token_type":"Bearer",
- "expires_in":86400
-}
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": "/oauth/token",
- "link": "#authorization-code-pkce-"
-}) %>
-
-This is the OAuth 2.0 grant that mobile apps utilize in order to access an API. Use this endpoint to exchange an Authorization Code for a Token.
-
-
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `grant_type` Required | Denotes the flow you are using. For Authorization Code (PKCE) use `authorization_code`. |
-| `client_id` Required | Your application's Client ID. |
-| `code` Required | The Authorization Code received from the initial `/authorize` call. |
-| `code_verifier` Required | Cryptographically random key that was used to generate the `code_challenge` passed to `/authorize`. |
-| `redirect_uri` | This is required only if it was set at the [GET /authorize](#authorization-code-grant-pkce-) endpoint. The values must match. |
-
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-If you have just executed the [Authorization Code Grant (PKCE)](#authorization-code-grant-pkce-) you should already have the **Authorization Code** and **Code Verifier** fields, of the *OAuth2 / OIDC* tab, set. If so, click **OAuth2 Code Exchange**, otherwise follow the instructions.
-
-1. At the *Configuration* tab, set the **Client** field to the application you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the field **Authorization Code** to the code you retrieved from [Authorization Code Grant](#authorization-code-grant-pkce-), and the **Code Verifier** to the key. Click **OAuth2 Code Exchange**.
-
-
-### More Information
-
-- [Calling APIs from Mobile Apps](/api-auth/grant/authorization-code-pkce)
-- [Executing an Authorization Code Grant Flow with PKCE](/api-auth/tutorials/authorization-code-grant-pkce)
-
-
-## Client Credentials
-
-```http
-POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "audience": "API_IDENTIFIER",
- "grant_type": "client_credentials",
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET"
-}
-```
-
-```shell
-curl --request POST \
- --url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"audience":"API_IDENTIFIER", "grant_type":"client_credentials", "client_id":"${account.clientId}", "client_secret":"YOUR_CLIENT_SECRET"}'
-```
-
-```javascript
-var request = require("request");
-
-var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET',
- audience: 'API_IDENTIFIER',
- grant_type: 'client_credentials' },
- json: true };
-
-request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- console.log(body);
-});
-```
-
-> RESPONSE SAMPLE:
-
-```JSON
-HTTP/1.1 200 OK
-Content-Type: application/json
-{
- "access_token":"eyJz93a...k4laUWw",
- "token_type":"Bearer",
- "expires_in":86400
-}
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": "/oauth/token",
- "link": "#client-credentials"
-}) %>
-
-This is the OAuth 2.0 grant that server processes utilize in order to access an API. Use this endpoint to directly request an `access_token` by using the Client Credentials (a Client ID and a Client Secret).
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `grant_type` Required | Denotes the flow you are using. For Client Credentials use `client_credentials`. |
-| `client_id` Required | Your application's Client ID. |
-| `client_secret` Required | Your application's Client Secret. |
-| `audience` Required | The unique identifier of the target API you want to access. |
-
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Client** field to the application you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, click **OAuth2 Client Credentials**.
-
-
-### More Information
-
-- [Calling APIs from a Service](/api-auth/grant/client-credentials)
-- [Setting up a Client Credentials Grant using the Management Dashboard](/api-auth/config/using-the-auth0-dashboard)
-- [Asking for Access Tokens for a Client Credentials Grant](/api-auth/config/asking-for-access-tokens)
-
-
-## Resource Owner Password
-
-```http
-POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "grant_type": "password",
- "username": "USERNAME",
- "password": "PASSWORD",
- "audience": "API_IDENTIFIER",
- "scope": "SCOPE",
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET"
-}
-```
-
-```shell
-curl --request POST \
- --url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"grant_type":"password", "username":"USERNAME", "password":"PASSWORD", "audience":"API_IDENTIFIER", "scope":"SCOPE", "client_id": "${account.clientId}", "client_secret": "YOUR_CLIENT_SECRET"
- }'
-```
-
-```javascript
-var request = require("request");
-
-var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { grant_type: 'password',
- username: 'USERNAME',
- password: 'PASSWORD',
- audience: 'API_IDENTIFIER',
- scope: 'SCOPE',
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET' },
- json: true };
-
-request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- console.log(body);
-});
-```
-
-> RESPONSE SAMPLE:
-
-```JSON
-HTTP/1.1 200 OK
-Content-Type: application/json
-{
- "access_token":"eyJz93a...k4laUWw",
- "token_type":"Bearer",
- "expires_in":86400
-}
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": "/oauth/token",
- "link": "#resource-owner-password"
-}) %>
-
-:::warning
-This flow should only be used from highly trusted applications that **cannot do redirects**. If you can use redirect-based flows from your apps we recommend using the [Authorization Code Grant](#authorization-code-grant) instead.
-:::
-
-This is the OAuth 2.0 grant that highly trusted apps use in order to access an API. In this flow the end-user is asked to fill in credentials (username/password) typically using an interactive form in the user-agent (browser). This information is sent to the backend and from there to Auth0. It is therefore imperative that the application is absolutely trusted with this information. For [client side](/api-auth/grant/implicit) applications and [mobile apps](/api-auth/grant/authorization-code-pkce) we recommend using web flows instead.
-
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `grant_type` Required | Denotes the flow you are using. For Resource Owner Password use `password`. To add realm support use `http://auth0.com/oauth/grant-type/password-realm`. |
-| `client_id` Required | Your application's Client ID. |
-| `client_secret` | Your application's Client Secret. **Required** when the **Token Endpoint Authentication Method** field at your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings) is `Post` or `Basic`. |
-| `audience` | The unique identifier of the target API you want to access. |
-| `username` Required | Resource Owner's identifier. |
-| `password` Required | Resource Owner's secret. |
-| `scope` | String value of the different scopes the application is asking for. Multiple scopes are separated with whitespace. |
-| `realm` | String value of the realm the user belongs. Set this if you want to add realm support at this grant. For more information on what realms are refer to [Realm Support](/api-auth/grant/password#realm-support). |
-
-### Request headers
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `auth0-forwarded-for` | End-user IP as a string value. Set this if you want brute-force protection to work in server-side scenarios. For more information on how and when to use this header, refer to [Using resource owner password from server-side](/api-auth/tutorials/using-resource-owner-password-from-server-side). |
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Client** field to the application you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the **Username** and **Password**, and click **Password Grant**.
-
-
-### Remarks
-
-- The scopes issued to the application may differ from the scopes requested. In this case, a `scope` parameter will be included in the response JSON.
-- If you don't request specific scopes, all scopes defined for the audience will be returned due to the implied trust to the application in this grant. You can customize the scopes returned in a rule. For more information, refer to [Calling APIs from Highly Trusted Applications](/api-auth/grant/password).
-- To add realm support set the `grant_type` to `http://auth0.com/oauth/grant-type/password-realm`, and the `realm` to the realm the user belongs. This maps to a connection in Auth0. For example, if you have configured a database connection for your internal employees and you have named the connection `employees`, then use this value. For more information on how to implement this refer to: [Realm Support](/api-auth/tutorials/password-grant#realm-support).
-- In addition to username and password, Auth0 may also require the end-user to provide an additional factor as proof of identity before issuing the requested scopes. In this case, the request described above will return an `mfa_required` error along with an `mfa_token`. You can use these tokens to request a challenge for the possession factor and validate it accordingly. For details refer to [Resource Owner Password and MFA](#resource-owner-password-and-mfa).
-
-### More Information
-- [Calling APIs from Highly Trusted Applications](/api-auth/grant/password)
-- [Executing the Resource Owner Password Grant](/api-auth/tutorials/password-grant)
-- [Multifactor Authentication and Resource Owner Password](/api-auth/tutorials/multifactor-resource-owner-password)
-
-## Refresh Token
-
-```http
-POST https://${account.namespace}/oauth/token
-Content-Type: application/json
-{
- "grant_type": "refresh_token",
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET",
- "refresh_token": "YOUR_REFRESH_TOKEN"
-}
-```
-
-```shell
-curl --request POST \
- --url 'https://${account.namespace}/oauth/token' \
- --header 'content-type: application/json' \
- --data '{"grant_type":"refresh_token","client_id": "${account.clientId}","client_secret": "YOUR_CLIENT_SECRET","refresh_token": "YOUR_REFRESH_TOKEN"}'
-```
-
-```javascript
-var request = require("request");
-
-var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/token',
- headers: { 'content-type': 'application/json' },
- body:
- { grant_type: 'refresh_token',
- client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET',
- refresh_token: 'YOUR_REFRESH_TOKEN'},
- json: true };
-
-request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- console.log(body);
-});
-```
-
-> RESPONSE SAMPLE:
-
-```JSON
-HTTP/1.1 200 OK
-Content-Type: application/json
-{
- "access_token": "eyJ...MoQ",
- "expires_in": 86400,
- "scope": "openid offline_access",
- "id_token": "eyJ...0NE",
- "token_type": "Bearer"
-}
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": "/oauth/token",
- "link": "#refresh-token"
-}) %>
-
-Use this endpoint to refresh an Access Token using the Refresh Token you got during authorization.
-
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `grant_type` Required | Denotes the flow you are using. To refresh a token, use `refresh_token`. |
-| `client_id` Required | Your application's Client ID. |
-| `client_secret` | Your application's Client Secret. **Required** when the **Token Endpoint Authentication Method** field at your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings) is `Post` or `Basic`. |
-| `refresh_token` Required | The Refresh Token to use. |
-
-
-### Test this endpoint
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Client** field to the client you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Client Settings](${manage_url}/#/clients/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the field **Refresh Token** to the Refresh Token you have. Click **OAuth2 Refresh Token Exchange**.
-
-
-### More Information
-
-- [Refresh Token](/tokens/refresh-token)
diff --git a/articles/api/authentication/api-authz/_highly-regulated.md b/articles/api/authentication/api-authz/_highly-regulated.md
new file mode 100644
index 0000000000..0181295d99
--- /dev/null
+++ b/articles/api/authentication/api-authz/_highly-regulated.md
@@ -0,0 +1,233 @@
+
+# Authorization Code Flow with Enhanced Privacy Protection
+
+## Push Authorization Requests (PAR)
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "POST",
+ "path": "/oauth/par",
+ "link": "##push-authorization-requests-par-"
+}) %>
+
+```http
+POST ${account.namespace}/oauth/par
+Content-Type: 'application/x-www-form-urlencoded'
+ audience={https://yourApi/}&
+ response_type=code|code id_token&
+ client_id={yourClientId}&
+ redirect_uri={https://yourApp/callback}&
+ state=STATE&
+ scope=openid|profile|email&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256&
+ nonce=NONCE&
+ connection=CONNECTION&
+ prompt=login|consent|none&
+ organisation=ORGANIZATION
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://{yourDomain}/oauth/par,
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form: {
+ audience: '{https://yourApi/}',
+ response_type: 'code|code id_token',
+ client_id: '{yourClientId}',
+ redirect_uri: '{https://yourApp/callback}',
+ state: 'STATE',
+ scope: 'openid|profile|email',
+ authorization_details: JSON.stringify([{ type: 'my_type' }]),
+ code_challenge: 'CODE_CHALLENGE',
+ code_challenge_method: 'S256',
+ nonce: 'NONCE',
+ connection: 'CONNECTION',
+ prompt: 'login|consent|none'
+ organisation: 'ORGANIZATION'
+ }
+};
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+
+```
+
+```shell
+curl --request POST \
+ --url 'https://{yourDomain}/oauth/par' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+--data 'audience={https://yourApi/}response_type=code|code id_token&client_id={yourClientId}&redirect_uri={https://yourApp/callback}&state=STATE&scope=openid|profile|email&authorization_details='[{"type":"my_type"}]'
+&code_challenge=CODE_CHALLENGE&code_challenge_method=S256&nonce=NONCE&connection=CONNECTION&prompt=login|consent|none&organisation=ORGANIZATION'
+
+```
+
+> RESPONSE SAMPLE:
+
+``` json
+/**
+If the request is successful, `/oauth/par` responds with a `JSON` object containing the `request_uri` property, which can be used at the authorization endpoint, and the `expires_in` value, which indicates the number of seconds the `request_uri` is valid.
+*/
+
+HTTP/1.1 201 Created
+Content-Type: application/json
+
+{
+ "request_uri":
+ "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
+ "expires_in": 30
+}
+```
+
+::: note
+To use Highly Regulated Identity features, you must have an Enterprise Plan with the Highly Regulated Identity add-on. Refer to [Auth0 Pricing](https://auth0.com/pricing) for details.
+:::
+
+Authorization Code Flow with [Pushed Authorization Requests (PAR)](/get-started/authentication-and-authorization-flow/authorization-code-flow/authorization-code-flow-with-par) uses the `/oauth/par` endpoint to allow applications to send the authorization parameters usually sent in a `GET` request to `/authorize`. PAR uses a POST method from the backend to keep parameter values secure. The `/oauth/par` endpoint accepts all authorization parameters which can be proivided to `/authorize`. Assuming the call to the `/oauth/par` endpoint is valid, Auth0 will respond with a `redirect_uri` value that can be used as a parameter for the `/authorize` endpoint.
+
+Assuming the call to the `/oauth/par` endpoint is valid, Auth0 will respond with a `redirect_uri` value also used as a parameter for the `/authorize` endpoint. To learn more about configuring PAR, read [Configure Pushed Authorization Requests (PAR)](/get-started/applications/configure-par).
+
+### Request Parameters
+| Parameter | Description |
+|:-----------------|:------------|
+|`authorization_details`| Requested permissions for each resource. Similar to scopes. To learn more, read [RAR reference documention](https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow/authorization-code-flow-with-rar). |
+|`audience`| The unique identifier of the target API you want to access. |
+| `response_type` Required | Specifies the token type. We recommend you use `code` to request an authorization code, or code `id_token` to receive an authorization code and a [detached signature](https://openid.net/specs/openid-financial-api-part-2-1_0.html#id-token-as-detached-signature). |
+| `client_id` Required | The `client_id` of your application. |
+| `redirect_uri` Required | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. Specify the `redirect_uri` under your [Application's Settings](${manage_url}/#/applications).|
+| `state` Recommended | An opaque value the application adds to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks. |
+| `scope` Recommended| OIDC scopes and custom API scopes. For example: `openid read:timesheets`. Include `offline_access` to get a refresh token.|
+| `code_challenge` Recommended | OIDC scopes and custom API scopes. For example: `openid read:timesheets`. Include `offline_access` to get a refresh token. |
+| `code_challenge_method` Recommended | Method used to generate the challenge. The PKCE specification defines two methods, `S256` and plain, however, Auth0 supports only S256 since the latter is discouraged. [Authorization Code Flow with Proof Key for Code Exchange (PKCE)] (/get-started/authentication-and-authorization-flow/authorization-code-flow-with-pkce).|
+| `nonce` Recommended | A string value which will be included in the ID token response from Auth0, used to prevent token replay attacks. It is required for `response_type=id_token` token. |
+| `connection` | The name of the connection configured to your application. If null, it will redirect to the [Auth0 Login Page](https://${account.namespace}/login) and show the Login Widget using the first database connection. |
+| `prompt` | Can be used to force a particular prompt to display, e.g. `prompt=consent` will always display the consent prompt.|
+| `organization` | ID of the organization to use when authenticating a user. When not provided, if your application is configured to **Display Organization Prompt**, the user will be able to enter the organization name when authenticating. |
+
+### Remarks
+- To make a call to the PAR endpoint, you must:
+ - Set the request content type as `application/x-www-form-urlencoded`
+ - Use `strings` for all passed parameters
+ - Include an additional parameter for application authentication in the request (e.g. `client_secret`, or `client_assertion` and `client_assertion_type` for JSON Web Token Client Authentication, or pass a `client-certificate` and `client-certificate-ca-verified` header when using Mutual TLS).
+- Use the `authorization_details` parameter to request permission for each resource. For example, you can specify an array of JSON objects to convey fine-grained information on the authorization. Each JSON object must contain a `type` attribute. The rest is up to you to define.
+
+## Authorize
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "GET",
+ "path": "/authorize",
+ "link": "#redirect-from-par-to-authorize"
+}) %>
+
+```http
+GET https://{yourDomain}/authorize
+ request_uri={yourRequestUri}&
+ client_id={yourClientId}
+```
+
+After calling the `/oauth/par` endpoint, redirect the end user to the `/authorize` endpoint using a `GET` call.
+
+:::note
+The `/authorize` endpoint will respond based on the parameters passed to the `/oauth/par` endpoint. If you request a `response_type`, you should receive an authorization code to use at the `/oauth/token` endpoint.
+:::
+
+### Request Parameters
+| Parameter | Description |
+|:-----------------|:------------|
+| `client_id` Required | The `client_id` of your application. |
+| `request_uri` Required | The `request_uri` value that was received from the `/oauth/par` endpoint. |
+
+## Exchange an Authorization Code for a Token
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#exchange-an-authorization-code-for-a-token"
+}) %>
+
+```http
+POST https://{yourDomain}/oauth/par
+Content-Type: 'application/x-www-form-urlencoded'
+ grant_type=code|code id_token&
+ client_id={yourClientId}&
+ code=CODE&
+ redirect_uri={https://yourApp/callback}&
+ code_verifier=CODE_VERIFIER
+```
+
+```javascript
+curl --request POST \
+ --url 'https://{yourDomain}/oauth/par' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+--data 'grant_type=authorization_code& client_id={yourClientId}& code=CODE&redirect_uri={https://yourApp/callback}&code_verifier=CODE_VERIFIER'
+```
+
+```shell
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://{yourDomain}/oauth/token,
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form: {
+ grant_type: 'authorization_code',
+ client_id: '{yourClientId}',
+ code: 'CODE',
+ redirect_uri: '{https://yourApp/callback}',
+ code_verifier: 'CODE_VERIFIER'
+ }
+};
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+``` json
+/**
+The `/oauth/token` endpoint will respond with a JSON object containing an `id_token` property, and potentially also a `refresh_token` if one was requested.
+*/
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "refresh_token":"GEbRxBN...edjnXbL",
+ "access_token":"eybRxBN...edjnXZQ",
+ "id_token":"eyJ0XAi...4faeEoQ",
+ "token_type":"Bearer",
+ "expires_in":86400,
+ "authrorization_details":[
+ {
+ "type":"my_type",
+ "other_attributes_of_my_type":"value"}
+ ]
+},
+
+
+```
+
+When users are redirected back to your callback, you need to make a `POST` call to the `oauth/token` endpoint to exchange an authorization code for an access and/or an ID token.
+
+### Request Parameters
+| Parameter | Description |
+|:-----------------|:------------|
+| `grant_type` Required | Denotes the flow. Assuming you have an authorization code from the `/authorize` endpoint, use `authorization_code`. |
+| `code` | The authorization code from the initial `/authorize` call. |
+| `client_id` Required | The `client_id` of your application. |
+| `request_uri` Required | This is required only if it was set at the `GET` `/oauth/par` endpoint. The values from `/authorize` must match the value you set at `/oauth/token`. |
+| `code_verifier` Recommended | Cryptographically random key used to generate the `code_challenge` passed to `/oauth/par`. If the `code_challenge` parameter is passed in the call to `/oauth/par`, this is required. |
+
+### Remarks
+
+To make a call to `/oauth/token` endpoint, you must:
+- Set the request content type as `application/x-www-form-urlencoded`
+- Use `strings` for all passed parameters
+- Include an additional parameter for application authentication in the request (e.g. `client_secret`, or `client_assertion` and `client_assertion_type` for JSON Web Token Client Authentication, or pass a `client-certificate` and `client-certificate-ca-verified` header when using Mutual TLS).
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_implicit.md b/articles/api/authentication/api-authz/_implicit.md
new file mode 100644
index 0000000000..a6bf10fdb7
--- /dev/null
+++ b/articles/api/authentication/api-authz/_implicit.md
@@ -0,0 +1,60 @@
+# Implicit Flow
+## Authorize
+
+```http
+GET https://${account.namespace}/authorize?
+ audience=API_IDENTIFIER&
+ scope=SCOPE&
+ response_type=token|id_token|id_token token&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ state=STATE&
+ nonce=NONCE
+```
+
+> RESPONSE SAMPLE
+
+```text
+HTTP/1.1 302 Found
+Location: ${account.callback}#access_token=TOKEN&state=STATE&token_type=TYPE&expires_in=SECONDS
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-primary",
+ "http_method": "GET",
+ "path": "/authorize",
+ "link": "#implicit-grant"
+}) %>
+
+This is the OAuth 2.0 grant that web apps utilize in order to access an API.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `audience` | The unique identifier of the target API you want to access. |
+| `scope` | The scopes which you want to request authorization for. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`. Custom claims that must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). |
+| `response_type` Required | This will specify the type of token you will receive at the end of the flow. Use `token` to get only an Access Token, `id_token` to get only an ID token (if you don't plan on accessing an API), or `id_token token` to get both an ID token and an Access Token. |
+| `client_id` Required | Your application's ID. |
+| `state` Recommended | An opaque value the application adds to the initial request that Auth0 includes when redirecting back to the application. This value must be used by the application to prevent CSRF attacks. |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. |
+| `nonce` Recommended | A string value which will be included in the ID token response from Auth0, [used to prevent token replay attacks](/api-auth/tutorials/nonce). It is required for `response_type=id_token token`. |
+| `connection` | The name of the connection configured for your application. |
+| `prompt` | To initiate a [silent authentication](/api-auth/tutorials/silent-authentication) request, use `prompt=none` (To learn more, read the Remarks). |
+| `organization` | ID of the [organization](/organizations) to use when authenticating a user. When not provided, if your application is configured to **Display Organization Prompt**, the user will be able to enter the organization name when authenticating. |
+| `invitation` | Ticket ID of the organization invitation. When [inviting a member to an Organization](/organizations/invite-members), your application should handle invitation acceptance by forwarding the invitation and organization key-value pairs when the user accepts the invitation. |
+
+### Remarks
+
+- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications).
+- If `response_type=token`, after the user authenticates with the provider, this will redirect them to your application callback URL while passing the `access_token` in the address `location.hash`. This is used for Single-Page Apps and on Native Mobile SDKs.
+- The Implicit Grant does not support the issuance of Refresh Tokens. Use [Silent Authentication](/api-auth/tutorials/silent-authentication) instead.
+- In order to improve compatibility for applications, Auth0 will now return profile information in a [structured claim format as defined by the OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that in order to add custom claims to ID tokens or Access Tokens, they must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims.
+- Silent Authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page. When an Access Token has expired, silent authentication can be used to retrieve a new one without user interaction, assuming the user's Single Sign-on (SSO) session has not expired.
+
+### Learn More
+
+- [Implicit Flow](/flows/concepts/implicit)
+- [State Parameter](/protocols/oauth2/oauth-state)
+- [Mitigate replay attacks when using the Implicit Grant](/api-auth/tutorials/nonce)
+- [Silent Authentication](/api-auth/tutorials/silent-authentication)
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_refresh-token.md b/articles/api/authentication/api-authz/_refresh-token.md
new file mode 100644
index 0000000000..ebd8bbdba7
--- /dev/null
+++ b/articles/api/authentication/api-authz/_refresh-token.md
@@ -0,0 +1,72 @@
+# Refresh Token
+
+```http
+POST https://${account.namespace}/oauth/token
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=refresh_token&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&refresh_token=YOUR_REFRESH_TOKEN
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/token' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'grant_type=refresh_token&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET&refresh_token=YOUR_REFRESH_TOKEN'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/token',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
+ { grant_type: 'refresh_token',
+ client_id: '${account.clientId}',
+ client_secret: 'YOUR_CLIENT_SECRET',
+ refresh_token: 'YOUR_REFRESH_TOKEN'}
+ };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "access_token": "eyJ...MoQ",
+ "expires_in": 86400,
+ "scope": "openid offline_access",
+ "id_token": "eyJ...0NE",
+ "token_type": "Bearer"
+}
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#refresh-token"
+}) %>
+
+Use this endpoint to refresh an Access Token using the Refresh Token you got during authorization.
+
+## Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `grant_type` Required | Denotes the flow you are using. To refresh a token, use `refresh_token`. |
+| `client_id` Required | Your application's Client ID. |
+| `client_secret` | Your application's Client Secret. Required when the **Token Endpoint Authentication Method** field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. |
+| `refresh_token` Required | The refresh token to use. |
+| `scope` | A space-delimited list of requested scope permissions. If not sent, the original scopes will be used; otherwise you can request a reduced set of scopes. Note that this must be URL encoded. |
+
+## Learn More
+
+- [Refresh Tokens](/tokens/concepts/refresh-tokens)
diff --git a/articles/api/authentication/api-authz/_resource-owner.md b/articles/api/authentication/api-authz/_resource-owner.md
new file mode 100644
index 0000000000..c8ce53f4ab
--- /dev/null
+++ b/articles/api/authentication/api-authz/_resource-owner.md
@@ -0,0 +1,96 @@
+# Resource Owner Password Flow
+## Get Token
+
+```http
+POST https://${account.namespace}/oauth/token
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=password&username=USERNAME&password=PASSWORD&audience=API_IDENTIFIER&scope=SCOPE&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/token' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'grant_type=password&username=USERNAME&password=PASSWORD&audience=API_IDENTIFIER&scope=SCOPE&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/token',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
+ { grant_type: 'password',
+ username: 'USERNAME',
+ password: 'PASSWORD',
+ audience: 'API_IDENTIFIER',
+ scope: 'SCOPE',
+ client_id: '${account.clientId}',
+ client_secret: 'YOUR_CLIENT_SECRET' }
+ };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "access_token":"eyJz93a...k4laUWw",
+ "token_type":"Bearer",
+ "expires_in":86400
+}
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#resource-owner-password"
+}) %>
+
+:::warning
+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](#regular-web-app-login-flow) instead.
+:::
+
+This is the OAuth 2.0 grant that highly-trusted apps use to access an API. In this flow, the end-user is asked to fill in credentials (username/password), typically using an interactive form in the user-agent (browser). This information is sent to the backend and from there to Auth0. It is therefore imperative that the application is absolutely trusted with this information. For [single-page applications and native/mobile apps](/flows/concepts/auth-code-pkce), we recommend using web flows instead.
+
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `grant_type` Required | Denotes the flow you are using. For Resource Owner Password use `password`. To add realm support use `http://auth0.com/oauth/grant-type/password-realm`. |
+| `client_id` Required | Your application's Client ID. |
+| `client_secret` | Your application's Client Secret. Required when the Token Endpoint Authentication Method field at your [Application Settings](${manage_url}/#/applications) is `Post` or `Basic`. |
+| `audience` | The unique identifier of the target API you want to access. |
+| `username` Required | Resource Owner's identifier, such as a username or email address. |
+| `password` Required | Resource Owner's secret. |
+| `scope` | String value of the different scopes the application is asking for. Multiple scopes are separated with whitespace. |
+| `realm` | String value of the realm the user belongs. Set this if you want to add realm support at this grant. For more information on what realms are refer to [Realm Support](/api-auth/grant/password#realm-support). |
+
+### Request headers
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `auth0-forwarded-for` | End-user IP as a string value. Set this if you want brute-force protection to work in server-side scenarios. For more information on how and when to use this header, refer to [Using resource owner password from server-side](/api-auth/tutorials/using-resource-owner-password-from-server-side). |
+
+### Remarks
+
+- The scopes issued to the application may differ from the scopes requested. In this case, a `scope` parameter will be included in the response JSON.
+- If you don't request specific scopes, all scopes defined for the audience will be returned due to the implied trust to the application in this grant. You can customize the scopes returned in a rule. For more information, refer to [Calling APIs from Highly Trusted Applications](/api-auth/grant/password).
+- To add realm support set the `grant_type` to `http://auth0.com/oauth/grant-type/password-realm`, and the `realm` to the realm the user belongs. This maps to a connection in Auth0. For example, if you have configured a database connection for your internal employees and you have named the connection `employees`, then use this value. For more information on how to implement this refer to: [Realm Support](/api-auth/tutorials/password-grant#realm-support).
+- In addition to username and password, Auth0 may also require the end-user to provide an additional factor as proof of identity before issuing the requested scopes. In this case, the request described above will return an `mfa_required` error along with an `mfa_token`. You can use these tokens to request a challenge for the possession factor and validate it accordingly. For details refer to [Resource Owner Password and MFA](#resource-owner-password-and-mfa).
+
+### Learn More
+- [Calling APIs from Highly-Trusted Applications](/api-auth/grant/password)
+- [Executing the Resource Owner Password Grant](/api-auth/tutorials/password-grant)
+- [Multi-factor Authentication and Resource Owner Password](/mfa/guides/mfa-api/multifactor-resource-owner-password)
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_revoke-refersh-token.md b/articles/api/authentication/api-authz/_revoke-refersh-token.md
deleted file mode 100644
index 7cc710f5f7..0000000000
--- a/articles/api/authentication/api-authz/_revoke-refersh-token.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# Revoke Refresh Token
-
-```http
-POST https://${account.namespace}/oauth/revoke
-Content-Type: application/json
-{
- "client_id": "${account.clientId}",
- "client_secret": "YOUR_CLIENT_SECRET",
- "token": "YOUR_REFRESH_TOKEN",
-}
-```
-
-```shell
-curl --request POST \
- --url 'https://${account.namespace}/oauth/revoke' \
- --header 'content-type: application/json' \
- --data '{ "client_id": "${account.clientId}", "client_secret": "YOUR_CLIENT_SECRET", "token": "YOUR_REFRESH_TOKEN" }'
-```
-
-```javascript
-var request = require("request");
-
-var options = { method: 'POST',
- url: 'https://${account.namespace}/oauth/revoke',
- headers: { 'content-type': 'application/json' },
- body:
- { client_id: '${account.clientId}',
- client_secret: 'YOUR_CLIENT_SECRET',
- token: 'YOUR_REFRESH_TOKEN' },
- json: true };
-
-request(options, function (error, response, body) {
- if (error) throw new Error(error);
-
- console.log(body);
-});
-```
-
-> RESPONSE SAMPLE:
-
-```JSON
-HTTP/1.1 200 OK
-(empty-response-body)
-```
-
-<%= include('../../../_includes/_http-method', {
- "http_badge": "badge-success",
- "http_method": "POST",
- "path": "/oauth/revoke",
- "link": "#revoke-refresh-token"
-}) %>
-
-Use this endpoint to invalidate a Refresh Token if it has been compromised.
-
-Each revocation request invalidates not only the specific token, but all other tokens based on the same authorization grant. This means that **all Refresh Tokens that have been issued for the same user, application, and audience will be revoked**.
-
-### Request Parameters
-
-| Parameter | Description |
-|:-----------------|:------------|
-| `client_id` Required | Your application's Client ID. The application should match the one the Refresh Token was issued for. |
-| `client_secret` | Your application's Client Secret. Required for [confidential applications](/applications/application-types#confidential-applications). |
-| `token` Required | The Refresh Token you want to revoke. |
-
-### Remarks
-
-- For non-confidential applications that cannot keep the Client Secret safe (for example, native apps), the endpoint supports passing no Client Secret but the application itself must have the property `tokenEndpointAuthMethod` set to `none`. You can do this either from the UI ([Dashboard > Applications > Application Settings](${manage_url}/#/applications/${account.clientId}/settings)) or using the [Management API](/api/management/v2#!/Applications/patch_applications_by_id).
-
-### Error Codes
-
-For the complete error code reference for this endpoint refer to [Errors > POST /oauth/revoke](#post-oauth-revoke).
-
-### More Information
-
-- [Refresh Token](/tokens/refresh-token)
diff --git a/articles/api/authentication/api-authz/_revoke-refresh-token.md b/articles/api/authentication/api-authz/_revoke-refresh-token.md
new file mode 100644
index 0000000000..5f44c585e2
--- /dev/null
+++ b/articles/api/authentication/api-authz/_revoke-refresh-token.md
@@ -0,0 +1,79 @@
+# Revoke Refresh Token
+
+```http
+POST https://${account.namespace}/oauth/revoke
+Content-Type: application/json
+{
+ "client_id": "${account.clientId}",
+ "client_secret": "YOUR_CLIENT_SECRET",
+ "token": "YOUR_REFRESH_TOKEN",
+}
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/revoke' \
+ --header 'content-type: application/json' \
+ --data '{ "client_id": "${account.clientId}", "client_secret": "YOUR_CLIENT_SECRET", "token": "YOUR_REFRESH_TOKEN" }'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/revoke',
+ headers: { 'content-type': 'application/json' },
+ body:
+ { client_id: '${account.clientId}',
+ client_secret: 'YOUR_CLIENT_SECRET',
+ token: 'YOUR_REFRESH_TOKEN' },
+ json: true };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+(empty-response-body)
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/revoke",
+ "link": "#revoke-refresh-token"
+}) %>
+
+Use this endpoint to invalidate a Refresh Token if it has been compromised.
+
+The behaviour of this endpoint depends on the state of the [Refresh Token Revocation Deletes Grant](https://auth0.com/docs/tokens/refresh-tokens/revoke-refresh-tokens#refresh-tokens-and-grants) toggle.
+If this toggle is enabled, then each revocation request invalidates not only the specific token, but all other tokens based on the same authorization grant. This means that **all Refresh Tokens that have been issued for the same user, application, and audience will be revoked**.
+If this toggle is disabled, then only the refresh token is revoked, while the grant is left intact.
+
+## Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `client_id` Required | The `client_id` of your application. |
+| `client_assertion`| A JWT containing a signed assertion with your application credentials. Required when Private Key JWT is the application authentication method.|
+| `client_assertion_type`| The value is `urn:ietf:params:oauth:client-assertion-type:jwt-bearer`. Required when Private Key JWT is the application authentication method.|
+| `client_secret` | The `client_secret` of your application. Required when Client Secret Basic or Client Secret Post is the application authentication method. Specifically required for Regular Web Applications **only**. |
+| `token` Required | The Refresh Token you want to revoke. |
+
+## Remarks
+
+- For non-confidential applications that cannot keep the Client Secret safe (for example, native apps), the endpoint supports passing no Client Secret but the application itself must have the property `tokenEndpointAuthMethod` set to `none`. You can do this either from the UI ([Dashboard > Applications > Application Settings](${manage_url}/#/applications)) or using the [Management API](/api/management/v2#!/Applications/patch_applications_by_id).
+
+## Error Codes
+
+For the complete error code reference for this endpoint, refer to [Errors > POST /oauth/revoke](#post-oauth-revoke).
+
+## Learn More
+
+- [Refresh Tokens](/tokens/concepts/refresh-tokens)
\ No newline at end of file
diff --git a/articles/api/authentication/api-authz/_token-exchange-native-social.md b/articles/api/authentication/api-authz/_token-exchange-native-social.md
new file mode 100644
index 0000000000..e234380215
--- /dev/null
+++ b/articles/api/authentication/api-authz/_token-exchange-native-social.md
@@ -0,0 +1,89 @@
+# Token Exchange for Native Social
+
+```http
+POST https://${account.namespace}/oauth/token
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=SUBJECT_TOKEN&subject_token_type=SUBJECT_TOKEN_TYPE&client_id=${account.clientId}&audience=API_IDENTIFIER&scope=SCOPE
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/oauth/token' \
+ --header 'content-type: application/x-www-form-urlencoded' \
+ --data 'grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=SUBJECT_TOKEN&subject_token_type=SUBJECT_TOKEN_TYPE&client_id=${account.clientId}&audience=API_IDENTIFIER&scope=SCOPE'
+ }'
+```
+
+```javascript
+var request = require("request");
+
+var options = { method: 'POST',
+ url: 'https://${account.namespace}/oauth/token',
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
+ form:
+ { grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
+ subject_token: 'SUBJECT_TOKEN',
+ subject_token_type: 'SUBJECT_TOKEN_TYPE',
+ client_id: '${account.clientId}',
+ audience: 'API_IDENTIFIER',
+ scope: 'SCOPE',
+ };
+
+request(options, function (error, response, body) {
+ if (error) throw new Error(error);
+
+ console.log(body);
+});
+```
+
+> RESPONSE SAMPLE:
+
+```JSON
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+ "access_token": "eyJz93a...k4laUWw",
+ "id_token": "eyJ...0NE",
+ "refresh_token": "eyJ...MoQ",
+ "expires_in":86400,
+ "token_type":"Bearer"
+}
+```
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": "/oauth/token",
+ "link": "#token-exchange-native-social"
+}) %>
+
+:::warning
+This flow is intended for use with native social interactions **only**. Use of this flow outside of a native social setting is highly discouraged.
+:::
+
+When a non-browser-based solution (such as a mobile platform's SDK) authenticates the user, the authentication will commonly result in artifacts being returned to application code. In such situations, this grant type allows for the Auth0 platform to accept artifacts from trusted sources and issue tokens in response. In this way, apps making use of non-browser-based authentication mechanisms (as are common in native apps) can still retrieve Auth0 tokens without asking for further user interaction.
+
+Artifacts returned by this flow (and the contents thereof) will be determined by the `subject_token_type` and the tenant's configuration settings.
+
+## Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `auth0-forwarded-for` | End user IP as a string value. Set this if you want brute-force protection to work in server-side scenarios. To learn more about how and when to use this header, read [Using resource owner password from server-side](/api-auth/tutorials/using-resource-owner-password-from-server-side). |
+| `grant_type` Required | Denotes the flow you are using. For Token Exchange for Native Social, use `urn:ietf:params:oauth:grant-type:token-exchange`. |
+| `subject_token` Required | Externally-issued identity artifact representing the user. |
+| `subject_token_type` Required | Identifier that indicates the type of `subject_token`. |
+| `client_id` Required | Your application's Client ID. |
+| `audience` | The unique identifier of the target API you want to access. |
+| `scope` | String value of the different scopes the application is requesting. Multiple scopes are separated with whitespace. |
+| `user_profile` Only For `apple-authz-code` | Optional element used for native iOS interactions for which profile updates can occur. Expected parameter value will be JSON in the form of: `{ name: { firstName: 'John', lastName: 'Smith }}` |
+
+## Remarks
+
+- The scopes issued to the application may differ from the requested scopes. In this case, a `scope` parameter will be included in the response JSON.
+- If you don't request specific scopes, all scopes defined for the audience will be returned due to the implied trust to the application in this grant. You can customize the scopes returned in a rule. To learn more, read [Calling APIs from Highly Trusted Applications](/api-auth/grant/password).
+
+## Learn More
+- [Add Sign In with Apple to Native iOS Apps](/connections/apple-siwa/add-siwa-to-native-app)
+- [iOS Swift - Sign In with Apple Quickstart](/quickstart/native/ios-swift-siwa)
\ No newline at end of file
diff --git a/articles/api/authentication/errors/_errors.md b/articles/api/authentication/errors/_errors.md
index 83eba927d5..3b9163d8ae 100644
--- a/articles/api/authentication/errors/_errors.md
+++ b/articles/api/authentication/errors/_errors.md
@@ -1,46 +1,21 @@
# Standard Error Responses
The Authentication API may return the following HTTP Status Codes:
-
-
-
-
-
Status
-
Description
-
-
-
-
-
400
-
Bad Request
-
-
-
401
-
Unauthorized
-
-
-
403
-
Forbidden
-
-
-
404
-
Not Found
-
-
-
405
-
Method Not Allowed
-
-
-
429
-
Too Many Requests
-
-
-
500
-
Internal Server Error
-
-
-
503
-
Service Unavailable
-
-
-
+| Status | JSON Response |
+| :---------------- | :------------ |
+| 400 Bad Request|`{"error": "invalid_request", "error_description": "..."}`|
+| 400 Bad Request| `{"error": "invalid_request", "error_description": "..."}`|
+| 400 Bad Request| `{"error": "invalid_scope", "error_description": "Scope must be an array or a string"}`|
+| 401 Unauthorized| `{"error": "invalid_client", "error_description": "..."}`|
+| 401 Unauthorized| `{"error": "requires_validation", "error_description": "Suspicious request requires verification"}`|
+| 403 Forbidden| `{"error": "unauthorized_client", "error_description": "..."}`|
+| 403 Forbidden| `{"error": "access_denied", "error_description": "..."}`|
+| 403 Forbidden| `{"error": "access_denied", "error_description": "Unknown or invalid refresh token"}`|
+| 403 Forbidden| `{"error": "invalid_grant", "error_description": "..."}`|
+| 404 Not Found| `{"error": "endpoint_disabled", "error_description": "..."}`|
+| 405 Method Not Allowed| `{"error": "method_not_allowed", "error_description": "..."}`|
+| 429 Too Many Requests| `{"error": "too_many_requests", "error_description": "..."}`|
+| 500 Internal Server Error | |
+| 501 Not Implemented| `{"error": "unsupported_response_type", "error_description": "..."}`|
+| 501 Not Implemented| `{"error": "unsupported_grant_type", "error_description": "..."}`|
+| 503 Service Unavailable| `{"error": "temporarily_unavailable", "error_description": "..."}`|
\ No newline at end of file
diff --git a/articles/api/authentication/errors/_oauth-access_token.md b/articles/api/authentication/errors/_oauth-access_token.md
index 6572e237b4..44b0f7541e 100644
--- a/articles/api/authentication/errors/_oauth-access_token.md
+++ b/articles/api/authentication/errors/_oauth-access_token.md
@@ -1,36 +1,10 @@
# POST /oauth/access_token
-
-
-
-
Status
-
Response
-
-
-
-
-
400
-
{"error": "invalid_request", "error_description": "the connection was disabled"}The connection is not active or not enabled for your client_id
-
-
-
400
-
{"error": "invalid_request", "error_description": "the connection was not found"}
{"error": "invalid_request", "error_description": "invalid access_token: invalid_token"}The access_token is invalid or does not contain the scope you set
+| Status | JSON Response |
+| :--------------- |:------------- |
+| 400 Bad Request | `{"error": "invalid_request", "error_description": "the connection was disabled"}` The connection is not active or not enabled for your `client_id`.|
+| 400 Bad Request | `{"error": "invalid_request", "error_description": "the connection was not found"}` |
+| 400 Bad Request | `{"error": "invalid_request", "error_description": "missing client_id parameter"}` |
+| 400 Bad Request | `{"error": "invalid_request", "error_description": "missing access_token parameter"}` |
+| 401 Unauthorized | `{"error": "invalid_request", "error_description": "invalid access_token: invalid_token"}` The `access_token` is invalid or does not contain the set `scope`|
+| 403 Forbidden | `{"error": "unauthorized_client", "error_description": "invalid client"}` |
\ No newline at end of file
diff --git a/articles/api/authentication/errors/_oauth-revoke.md b/articles/api/authentication/errors/_oauth-revoke.md
index 4f5ce06019..cbca1e2779 100644
--- a/articles/api/authentication/errors/_oauth-revoke.md
+++ b/articles/api/authentication/errors/_oauth-revoke.md
@@ -1,24 +1,7 @@
# POST /oauth/revoke
-
-
-
-
Status
-
Description
-
-
-
-
-
200
-
{"error": "invalid_request", "error_description": "..."}The Refresh Token is revoked, does not exist, or was not issued to the client making the revocation request.
-
-
-
400
-
{"error": "invalid_request", "error_description": "..."}The required parameters were not sent in the request.
-
-
-
401
-
<{"error": "invalid_client", "error_description": "..."}The request is not authorized. Check that the client credentials (client_id and client_secret) are present in the request and hold valid values.
-
-
-
+| Status | JSON Response |
+| :--------------- | :------------ |
+|200 Success | `{"error": "invalid_request", "error_description": "..."}` The Refresh Token is revoked, does not exist, or was not issued to the client making the revocation request|
+|400 Bad Request | `{"error": "invalid_request", "error_description": "..."}` The required parameters were not sent in the request.|
+|401 Unauthorized | `{"error": "invalid_client", "error_description": "..."}` The request is not authorized. Check that the client credentials `client_id` and client_secret` are present in the request and hold valid values. |
\ No newline at end of file
diff --git a/articles/api/authentication/errors/_oauth-ro.md b/articles/api/authentication/errors/_oauth-ro.md
index 2dbfd6f52f..e552af873a 100644
--- a/articles/api/authentication/errors/_oauth-ro.md
+++ b/articles/api/authentication/errors/_oauth-ro.md
@@ -2,123 +2,33 @@
## Grant type: jwt-bearer
-
-
-
-
Status
-
Description
-
-
-
-
-
400
-
{"error": "invalid_request", "error_description": "missing device parameter"}You need to provide a device name for the caller device (like a browser, app, and so on)
-
-
-
400
-
{"error": "invalid_request", "error_description": "missing id_token parameter"}For this grant type you need to provide a JWT ID Token
-
-
-
400
-
{"error": "invalid_grant", "error_description": "..."}Errors related to an invalid id_token or user
-
-
-
+| Status | JSON Response |
+| :----------------| :------------ |
+|400 Bad Request|`{"error": "invalid_request", "error_description": "missing device parameter"}` You need to provide a device name for the caller device (like a browser, app, and so on) |
+|400 Bad Request|`{"error": "invalid_request", "error_description": "missing id_token parameter"}`For this grant type you need to provide a JWT ID Token |
+|400 Bad Request|`{"error": "invalid_grant", "error_description": "..."}` Errors related to an invalid ID Token or user |
## Grant type: password
-
{"error": "invalid_request", "error_description": "scope parameter must be a string"}Incorrect scope formatting; each scope must be separated by whitespace
-
-
-
400
-
{"error": "invalid_request", "error_description": "specified strategy does not support requested operation"}The connection/provider does not implement username/password authentication
-
-
-
401
-
{"error": "invalid_user_password", "error_description": "Wrong email or password."}
-
-
-
401
-
{"error": "unauthorized", "error_description": "user is blocked"}
-
-
-
401
-
{ "error": "password_leaked", "error_description": "This login has been blocked because your password has been leaked in another website. We’ve sent you an email with instructions on how to unblock it."}
-
-
-
429
-
{"error": "too_many_attempts", "error_description": "..."}Some anomaly detections will return this error
-
-
-
429
-
{"error": "too_many_logins", "error_description": "..."}Some anomaly detections will return this error
-
-
-
+| Status | JSON Response |
+| :----------------| :------------ |
+| 400 Bad Request|`{"error": "invalid_request", "error_description": "scope parameter must be a string"}` Incorrect scope formatting; each scope must be separated by whitespace|
+| 400 Bad Request|`{"error": "invalid_request", "error_description": "specified strategy does not support requested operation"}`The connection/provider does not implement username/password authentication |
+| 401 Unauthorized|`{"error": "invalid_user_password", "error_description": "Wrong email or password."}`|
+| 401 Unauthorized|`{"error": "unauthorized", "error_description": "user is blocked"}`|
+| 401 Unauthorized|`{ "error": "password_leaked", "error_description": "This login has been blocked because your password has been leaked in another website. We’ve sent you an email with instructions on how to unblock it."}`|
+| 401 Unauthorized|`{ "error": "requires_verification", "error_description": "Suspicious request requires verification" }`|
+| 429 Too Many Requests|`{"error": "too_many_attempts", "error_description": "..."}` Some attack protection features will return this error|
+| 429 Too Many Requests|`{"error": "too_many_logins", "error_description": "..."}` Some attack protection features will return this error|
## All grant types
-
{"error": "invalid_request", "error_description": "the connection was not found"}
-
-
-
400
-
{"error": "invalid_request", "error_description": "the connection was disabled"}Check the connection in the dashboard, you may have turned it off for the provided client_id
-
-
-
400
-
{"error": "invalid_request", "error_description": "The connection is not yet configured..."}The connection is not properly configured with custom scripts
-
-
-
400
-
{"error": "invalid_request", "error_description": "the connection was not found for tenant..."}The connection does not belong to the tenant; check your base url
-
-
-
400
-
{"error": "invalid_request", "error_description": "Fields with "." are not allowed, please remove all dotted fields..."}If you are using rules, some field name contains dots
-
-
-
403
-
{"error": "unauthorized_client", "error_description": "invalid client"}The provided client_id is not valid
-
-
-
403
-
{"error": "access_denied", "error_description": "..."}Validation of specific points raised an access issue
-
-
-
+| Status | JSON Response |
+| :--------------- | :----------- |
+| 400 Bad Request |`{"error": "invalid_request", "error_description": "missing client_id parameter"}<`|
+| 400 Bad Request |`{"error": "invalid_request", "error_description": "the connection was disabled"}`Check the connection in the dashboard, you may have turned it off for the provided `client_id` |
+| 400 Bad Request |`{"error": "invalid_request", "error_description": "The connection is not yet configured..."}` The connection is not properly configured with custom scripts|
+| 400 Bad Request |`{"error": "invalid_request", "error_description": "the connection was not found for tenant..."}`The connection does not belong to the tenant; check your base url |
+| 400 Bad Request |`{"error": "invalid_request", "error_description": "Fields with "." are not allowed, please remove all dotted fields..."}`If you are using rules, some field name contains dots |
+| 403 Forbidden |`{"error": "unauthorized_client", "error_description": "invalid client"}`The provided `client_id` is not valid |
+| 403 Forbidden |`{"error": "access_denied", "error_description": "..."}`Validation of specific points raised an access issue |
\ No newline at end of file
diff --git a/articles/api/authentication/errors/_passwordless-start.md b/articles/api/authentication/errors/_passwordless-start.md
index 15814aa9ac..348b707a16 100644
--- a/articles/api/authentication/errors/_passwordless-start.md
+++ b/articles/api/authentication/errors/_passwordless-start.md
@@ -1,56 +1,25 @@
+
# POST /passwordless/start
-
-
-
-
Status
-
Response
-
-
-
-
-
400
-
{"error": "bad.tenant","error_description": "error in tenant - tenant validation failed: invalid_tenant"}
+| Status | JSON Response |
+| :----------------| :------------ |
+|400 Bad Request|`{"error": "bad.tenant","error_description": "error in tenant - tenant validation failed: invalid_tenant"}`|
+|400 Bad Request|`{"error": "bad.client_id", "error_description": "Missing required property: client_id"}`|
+|400 Bad Request|`{"error": "bad.connection", "error_description": "Missing required property: connection"}`|
+|400 Bad Request|`{"error": "bad.connection", "error_description": "Connection does not exist"}`|
+|400 Bad Request|`{"error": "bad.connection", "error_description": "Connection is disabled"}`|
+|400 Bad Request|`{"error": "bad.connection", "error_description": "Invalid connection strategy. It must either be a passwordless connection"}`|
+|400 Bad Request|`{"error": "bad.authParams", "error_description": "error in authParams - invalid type: string (expected object)"}`|
+|400 Bad Request|`{"error": "bad.request", "error_description": "the following properties are not allowed: "}`|
+|400 Bad Request|`{"error": "bad.phone_number", "error_description": "Missing required property: phone_number"}`|
+|400 Bad Request|`{"error": "bad.phone_number", "error_description": "String does not match pattern: ^\\+[0-9]{1,15}$"}`|
+|400 Bad Request|`{"error": "sms_provider_error", "error_description": " (Code: )"}`|
+|400 Bad Request|`{"error": "invalid_request","error_description": "Expected `auth0-forwarded-for` header to be a valid IP address."}`|
+|400 Bad Request|`{"error": "bad.tenant","error_description": "error in tenant - could not find tenant in params"}`|
+|400 Bad Request|`{"error": "server_error","error_description": "error resolving client"}`|
+|400 Bad Request|`{"error": "invalid_request","error_description": "The client_id in the authentication header does not match the client_id in the payload"}`|
+|400 Bad Request|`{"error": "bad.connection","error_description": "Public signup is disabled"}`|
+|400 Bad Request|`{"error": "bad.connection","error_description": "Unknown error"}`|
+|401 Unauthorized|`{"error": "server_error","error_description": "user is blocked"}`|
+|403 Forbidden|`{"error": "unauthorized_client","error_description": "Client authentication is required"}`|
+|500 Internal Server Error|`{"error": "server_error","error_description": "IdP Error"}`|
\ No newline at end of file
diff --git a/articles/api/authentication/errors/_passwordless-verify.md b/articles/api/authentication/errors/_passwordless-verify.md
new file mode 100644
index 0000000000..1ea71461b4
--- /dev/null
+++ b/articles/api/authentication/errors/_passwordless-verify.md
@@ -0,0 +1,22 @@
+# POST /passwordless/verify
+
+| Status | JSON Response |
+| :----------------| :------------ |
+|400 Bad Request|`{"error": "invalid_request", "error_description": "missing username parameter"}`|
+|400 Bad Request|`{"error": "invalid_request", "error_description": "scope parameter must be a string"}`Incorrect scope formatting; each scope must be separated by whitespace|
+|400 Bad Request|`{"error": "invalid_request", "error_description": "missing client_id parameter"}`|
+|400 Bad Request|`{"error": "invalid_request", "error_description": "the connection was not found"}`|
+|400 Bad Request|`{"error": "invalid_request", "error_description": "the connection was disabled"}` Check the connection in the dashboard, you may have turned it off for the provided `client_id`|
+|400 Bad Request|`{"error": "invalid_request", "error_description": "the connection was not found for tenant..."}` The connection does not belong to the tenant; check your base url|
+|400 Bad Request|`{"error": "invalid_request", "error_description": "Fields with "." are not allowed, please remove all dotted fields..."}`If you are using rules, some field name contains dots|
+|400 Bad Request|`"error": "bad.tenant","error_description": "error in tenant - could not find tenant in params"`|
+|400 Bad Request|`{"error": "bad.tenant","error_description": "error in tenant - tenant validation failed: "}`|
+|400 Bad Request|`{"error": "bad.connection","error_description": "Connection does not exist"}`|
+|400 Bad Request|`{"error": "bad.connection","error_description": "Invalid connection strategy. It must either be a passwordless connection"}`|
+|400 Bad Request|`{"error": "bad.connection","error_description": "The connection is disabled"}`|
+|401 Unauthorized|`{"error": "invalid_user_password", "error_description": "Wrong email or password."}`|
+|401 Unauthorized|`{"error": "unauthorized", "error_description": "user is blocked"}`|
+|403 Forbidden|`{"error": "unauthorized_client", "error_description": "invalid client"}`The provided `client_id` is not valid|
+|403 Forbidden|`{"error": "access_denied", "error_description": "..."}`Validation of specific points raised an access issue|
+|429 Too Many Requests|`{"error": "too_many_attempts", "error_description": "..."}` Some attack protection features will return this error|
+|500 Bad Request|`{"error": "server_error","error_description": "..."}`|
\ No newline at end of file
diff --git a/articles/api/authentication/index.md b/articles/api/authentication/index.md
index 32a55606b3..3edd4a539a 100644
--- a/articles/api/authentication/index.md
+++ b/articles/api/authentication/index.md
@@ -1,6 +1,9 @@
---
title: Authentication API Explorer
fullWidth: true
+contentType:
+ - index
+ - reference
---
+
+
diff --git a/articles/api/authentication/legacy/_delegation.md b/articles/api/authentication/legacy/_delegation.md
index bc32d1689a..a173755d24 100644
--- a/articles/api/authentication/legacy/_delegation.md
+++ b/articles/api/authentication/legacy/_delegation.md
@@ -1,5 +1,3 @@
-
-
# Delegation
```http
@@ -35,7 +33,7 @@ curl --request POST \
}) %>
::: warning
-This feature is disabled by default for new tenants as of 8 June 2017. See the [migration notice](/migrations#api-authorization-with-third-party-vendor-apis) for more information.
+By default, this feature is disabled for tenants without an add-on in use as of 8 June 2017. Legacy tenants who currently use an add-on that requires delegation may continue to use this feature. If delegation functionality is changed or removed from service at some point, customers who currently use it will be notified beforehand and given ample time to migrate.
:::
A delegation token can be obtained and used when an application needs to call the API of an Application Addon, such as Firebase or SAP, registered and configured in Auth0, in the same tenant as the calling program.
@@ -49,25 +47,10 @@ Given an existing token, this endpoint will generate a new token signed with the
| `client_id` Required | Τhe `client_id` of your app |
| `grant_type` Required | Use `urn:ietf:params:oauth:grant-type:jwt-bearer`|
| `id_token` or `refresh_token` Required | The existing token of the user. |
-| `target ` | The target `client_id` |
-| `scope ` | Use `openid` or `openid profile email` |
+| `target` | The target `client_id` |
+| `scope` | Use `openid` or `openid profile email` |
| `api_type` | The API to be called. |
-### Test with Postman
-
-<%= include('../../../_includes/_test-with-postman') %>
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Application** field to the app you want to use for the test.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the fields **ID Token**, **Refresh Token** and **Target Client ID**. Click **Delegation**.
-
-
### Remarks
- The `profile` scope value requests access to the End-User's default profile Claims, which are: `name`, `family_name`, `given_name`, `middle_name`, `nickname`, `preferred_username`, `profile`, `picture`, `website`, `gender`, `birthdate`, `zoneinfo`, `locale`, and `updated_at`.
@@ -84,8 +67,7 @@ Given an existing token, this endpoint will generate a new token signed with the
- `X-RateLimit-Reset`: Remaining time until the rate limit (`X-RateLimit-Limit`) resets. The value is in [UTC epoch seconds](https://en.wikipedia.org/wiki/Unix_time).
-### More Information
+### Learn More
- [Delegation Tokens](/tokens/delegation)
-
-- [Auth0 API Rate Limit Policy](/policies/rate-limits)
+- [Auth0 API Rate Limit Policy](/policies/rate-limits)
\ No newline at end of file
diff --git a/articles/api/authentication/legacy/_impersonation.md b/articles/api/authentication/legacy/_impersonation.md
new file mode 100644
index 0000000000..6fd286a04f
--- /dev/null
+++ b/articles/api/authentication/legacy/_impersonation.md
@@ -0,0 +1,81 @@
+# Impersonation
+
+```http
+POST https://${account.namespace}/users/{user_id}/impersonate
+Content-Type: application/json
+Authorization: 'Bearer {ACCESS_TOKEN}'
+{
+ protocol: "PROTOCOL",
+ impersonator_id: "IMPERSONATOR_ID",
+ client_id: "${account.clientId}",
+ additionalParameters: [
+ "response_type": "code",
+ "state": "STATE"
+ ]
+}
+```
+
+```shell
+curl --request POST \
+ --url 'https://${account.namespace}/users/{user_id}/impersonate' \
+ --header 'Authorization: Bearer {ACCESS_TOKEN}' \
+ --header 'content-type: application/x-www-form-urlencoded; charset=UTF-8' \
+ --data '{"protocol":"PROTOCOL", "impersonator_id":"IMPERSONATOR_ID", "client_id":"${account.clientId}", "additionalParameters": {"response_type": "code", "state": "STATE"}}'
+```
+
+```javascript
+var url = 'https://' + ${account.namespace} + '/users/' + localStorage.getItem('user_id') + '/impersonate';
+var params = 'protocol=PROTOCOL&impersonator_id=IMPERSONATOR_ID&client_id=${account.clientId}';
+
+var xhr = new XMLHttpRequest();
+
+xhr.open('POST', url);
+xhr.setRequestHeader('Content-Type', 'application/json');
+xhr.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('access_token'));
+
+xhr.onload = function() {
+ if (xhr.status == 200) {
+ fetchProfile();
+ } else {
+ alert("Request failed: " + xhr.statusText);
+ }
+};
+
+xhr.send(params);
+```
+
+> RESPONSE SAMPLE:
+
+```text
+https:/YOUR_DOMAIN/users/IMPERSONATOR_ID/impersonate?&bewit=WFh0MUtm...
+```
+
+<% var path = '/users/{user_id}/impersonate'; %>
+
+<%= include('../../../_includes/_http-method', {
+ "http_badge": "badge-success",
+ "http_method": "POST",
+ "path": path,
+ "link": "#impersonation"
+}) %>
+
+<%= include('../../../_includes/_deprecate-impersonation.md') %>
+
+Use this endpoint to obtain an impersonation URL to login as another user. Useful for troubleshooting.
+
+### Request Parameters
+
+| Parameter | Description |
+|:-----------------|:------------|
+| `protocol` Required | The protocol to use against the identity provider: `oauth2`, `samlp`, `wsfed`, `wsfed-rms`. |
+| `impersonator_id` Required | The `user_id` of the impersonator. |
+| `client_id` Required | The `client_id` of the client that is generating the impersonation link.|
+| `additionalParameters` | This is a JSON object. You can use this to set additional parameters, like `response_type`, `scope` and `state`. |
+
+### Remarks
+
+- This endpoint can only be used with **Global Client** credentials.
+
+- To distinguish between real logins and impersonation logins, the profile of the impersonated user will contain additional impersonated and impersonator properties. For example: `"impersonated": true, "impersonator": {"user_id": "auth0|...", "email": "admin@example.com"}`.
+
+- For a regular web app, you should set the `additionalParameters`: set the `response_type` to be `code`, the `callback_url` to be the callback URL to which Auth0 will redirect with the authorization code, and the `scope` to be the JWT claims that you want included in the JWT.
diff --git a/articles/api/authentication/legacy/_linking.md b/articles/api/authentication/legacy/_linking.md
index 6e42378c78..0e4b6657ce 100644
--- a/articles/api/authentication/legacy/_linking.md
+++ b/articles/api/authentication/legacy/_linking.md
@@ -1,7 +1,10 @@
# Account Linking
-
## Link
+::: warning
+This endpoint is **deprecated** for account linking. The [POST /api/v2/users/{id}/identities](/api/management/v2#!/Users/post_identities) should be used instead. For more information refer to the [Migration Notice](/migrations/past-migrations#account-linking-removal).
+:::
+
```http
GET https://${account.namespace}/authorize?
response_type=code|token&
@@ -18,13 +21,9 @@ GET https://${account.namespace}/authorize?
"link": "#link"
}) %>
-::: warning
-This endpoint is **deprecated** for account linking. The [POST /api/v2/users/{id}/identities](/api/management/v2#!/Users/post_identities) should be used instead. For more information refer to the [Migration Notice](/migrations/past-migrations#account-linking-removal).
-:::
-
Call this endpoint when a user wants to link a second authentication method (for example, a user/password database connection, with Facebook).
-This endpoint will trigger the login flow to link an existing account with a new one. This will return a 302 redirect to the `connection` that the current user wants to add. The user is identified by the `access_token` that was returned on login success.
+This endpoint will trigger the login flow to link an existing account with a new one. This will return a 302 redirect to the `connection` that the current user wants to add. The user is identified by the Access Token that was returned on login success.
### Request Parameters
@@ -40,14 +39,14 @@ This endpoint will trigger the login flow to link an existing account with a new
### Remarks
-- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
+- The `redirect_uri` value must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications).
-### More Information
+### Learn More
-- [Linking Accounts](/link-accounts)
-- [User Initiated Account Linking](/link-accounts/user-initiated-linking)
-- [Account Linking from Server Side Code](/link-accounts/suggested-linking)
+- [Link User Accounts](/users/guides/link-user-accounts)
+- [Link User Accounts Initiated by Users Scenario](/users/references/link-accounts-user-initiated-scenario)
+- [Link User Accounts Server-Side Scenario](/users/references/link-accounts-server-side-scenario)
## Unlink
@@ -56,7 +55,7 @@ This endpoint will trigger the login flow to link an existing account with a new
POST https://${account.namespace}/login/unlink
Content-Type: application/json
{
- "access_token": "LOGGED_IN_USER_ACCESS_TOKEN", // Primary identity access_token
+ "access_token": "LOGGED_IN_USER_ACCESS_TOKEN", // Primary identity Access Token
"user_id": "LINKED_USER_ID" // (provider|id)
}
```
@@ -95,7 +94,7 @@ xhr.send(params);
}) %>
::: warning
-This endpoint is **deprecated**. The [DELETE /api/v2/users/{id}/identities/{provider}/{user_id}](/api/management/v2#!/Users/delete_provider_by_user_id) should be used instead.
+This endpoint is **deprecated**. The [DELETE /api/v2/users/{id}/identities/{provider}/{user_id}](/api/management/v2#!/Users/delete_user_identity_by_user_id) should be used instead.
:::
Given a logged-in user's `access_token` and `user_id`, this endpoint will unlink a user's account from the identity provider.
@@ -105,15 +104,10 @@ Given a logged-in user's `access_token` and `user_id`, this endpoint will unlink
| Parameter | Description |
|:-----------------|:------------|
-| `access_token` Required | The logged-in user's `Access Token` |
+| `access_token` Required | The logged-in user's Access Token |
| `user_id` Required | The logged-in user's `user_id` |
-### Test with Postman
-
-<%= include('../../../_includes/_test-with-postman') %>
-
-
-### More Information
+### Learn More
-- [Unlinking Accounts](/link-accounts#unlinking-accounts)
+- [Unlink User Accounts](/users/guides/unlink-user-accounts)
diff --git a/articles/api/authentication/legacy/_login.md b/articles/api/authentication/legacy/_login.md
index b01992c62f..4c197080e9 100644
--- a/articles/api/authentication/legacy/_login.md
+++ b/articles/api/authentication/legacy/_login.md
@@ -1,7 +1,5 @@
-
# Login
-
## Social with Provider's Access Token
```http
@@ -62,24 +60,21 @@ xhr.send(params);
::: warning
This endpoint is part of the legacy authentication pipeline. We recommend that you open the browser to do social authentication instead, which is what [Google and Facebook are recommending](https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html). For more information on the latest authentication pipeline refer to [Introducing OIDC Conformant Authentication](/api-auth/intro).
-This feature is disabled by default for new tenants as of 8 June 2017. Please see [Application Grant Types](/applications/application-grant-types) for more information.
+This feature is disabled by default for new tenants as of 8 June 2017. Please see [Application Grant Types](/applications/concepts/application-grant-types) for more information.
:::
-Given the social provider's `access_token` and the `connection`, this endpoint will authenticate the user with the provider and return a JSON with the `access_token` and, optionally, an `id_token`. This endpoint only works for Facebook, Google, Twitter and Weibo.
+Given the social provider's Access Token and the `connection`, this endpoint will authenticate the user with the provider and return a JSON with the Access Token and, optionally, an ID Token. This endpoint only works for Facebook, Google, Twitter, and Weibo.
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
| `client_id` Required | The `client_id` of your application. |
-| `access_token` Required | The social provider's `access_token`. |
+| `access_token` Required | The social provider's Access Token. |
| `connection` Required | The name of an identity provider configured to your app. |
-| `scope` | Use `openid` to get an `id_token`, or `openid profile email` to include user information in the `id_token`. If null, only an `access_token` will be returned. |
+| `scope` | Use `openid` to get an ID Token, or `openid profile email` to include user information in the ID Token. If null, only an Access Token will be returned. |
-### Test with Postman
-
-<%= include('../../../_includes/_test-with-postman') %>
### Remarks
@@ -91,13 +86,11 @@ Given the social provider's `access_token` and the `connection`, this endpoint w
For the complete error code reference for this endpoint refer to [Errors > POST /oauth/access_token](#post-oauth-access_token).
-### More Information
+### Learn More
- [Call an Identity Provider API](/tutorials/calling-an-external-idp-api)
-
-- [Identity Provider Access Tokens](/tokens/idp)
-
-- [Add scopes/permissions to call Identity Provider's APIs](/tutorials/adding-scopes-for-an-external-idp)
+- [Identity Provider Access Tokens](/tokens/overview-idp-access-tokens)
+- [Add scopes/permissions to call Identity Provider's APIs](/connections/adding-scopes-for-an-external-idp)
## Database/AD/LDAP (Active)
@@ -169,7 +162,7 @@ curl --request POST \
This endpoint is part of the legacy authentication pipeline and has been replaced in favor of the [Password Grant](#resource-owner-password). For more information on the latest authentication pipeline refer to [Introducing OIDC Conformant Authentication](/api-auth/intro).
:::
-Use this endpoint for API-based (active) authentication. Given the user credentials and the `connection` specified, it will do the authentication on the provider and return a JSON with the `access_token` and `id_token`.
+Use this endpoint for API-based (active) authentication. Given the user credentials and the `connection` specified, it will do the authentication on the provider and return a JSON with the Access Token and ID Token.
### Request Parameters
@@ -179,29 +172,14 @@ Use this endpoint for API-based (active) authentication. Given the user credenti
| `username` Required | Username/email of the user to login |
| `password` Required | Password of the user to login |
| `connection` Required | The name of the connection to use for login |
-| `scope` | Set to `openid` to retrieve also an `id_token`, leave null to get only an `access_token` |
-| `grant_type` Required | Set to `password` to authenticate using username/password or `urn:ietf:params:oauth:grant-type:jwt-bearer` to authenticate using an `id_token` (used to [Authenticate users with Touch ID](/connections/passwordless/ios-touch-id-swift)) |
+| `scope` | Set to `openid` to retrieve also an ID Token, leave null to get only an Access Token |
+| `grant_type` Required | Set to `password` to authenticate using username/password or `urn:ietf:params:oauth:grant-type:jwt-bearer` to authenticate using an ID Token instead of username/password, in [Touch ID](/libraries/lock-ios/touchid-authentication) scenarios. |
| `device` | String value. Required when `grant_type` is `urn:ietf:params:oauth:grant-type:jwt-bearer` |
| `id_token` | Used to authenticate using a token instead of username/password, in [Touch ID](/libraries/lock-ios/touchid-authentication) scenarios. Required when `grant_type` is `urn:ietf:params:oauth:grant-type:jwt-bearer` |
-### Test with Postman
-
-<%= include('../../../_includes/_test-with-postman') %>
-
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the fields **Application** (select the application you want to use for the test) and **Connection** (the name of the social connection to use).
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set **Username** and **Password**. Click **Resource Owner Endpoint**.
-
-
### Remarks
-- This endpoint only works for database connections, passwordless connections, Active Directory/LDAP, Windows Azure AD and ADFS.
+- This endpoint only works for database connections, passwordless connections, Active Directory/LDAP, Windows Azure AD and ADFS.
- The main difference between passive and active authentication is that the former happens in the browser through the [Auth0 Login Page](https://${account.namespace}/login) and the latter can be invoked from anywhere (a script, server to server, and so forth).
@@ -210,14 +188,10 @@ Use this endpoint for API-based (active) authentication. Given the user credenti
### Error Codes
-For the complete error code reference for this endpoint refer to [Errors > POST /oauth/ro](#post-oauth-ro).
+For the complete error code reference for this endpoint, refer to [Errors > POST /oauth/ro](#post-oauth-ro).
-### More Information
+### Learn More
- [Database Identity Providers](/connections/database)
-
-- [Rate Limits on User/Password Authentication](/connections/database/rate-limits)
-
-- [Active Directory/LDAP Connector](/connector)
-
-- [Authenticate users with Touch ID](/connections/passwordless/ios-touch-id-swift)
+- [Rate Limits on User/Password Authentication](/policies/rate-limit-policy/database-connections-rate-limits)
+- [Active Directory/LDAP Connector](/connector)
\ No newline at end of file
diff --git a/articles/api/authentication/legacy/_resource-owner.md b/articles/api/authentication/legacy/_resource-owner.md
index bd3cb61a42..d191536587 100644
--- a/articles/api/authentication/legacy/_resource-owner.md
+++ b/articles/api/authentication/legacy/_resource-owner.md
@@ -65,10 +65,10 @@ request(options, function (error, response, body) {
}) %>
::: warning
-This endpoint is part of the legacy authentication pipeline and has been replaced in favor of the [Password Grant](#resource-owner-password). For more information on the latest authentication pipeline refer to [Introducing OIDC Conformant Authentication](/api-auth/intro).
+This endpoint is part of the legacy authentication pipeline and has been replaced in favor of the [Password Grant](#resource-owner-password-flow). For more information on the latest authentication pipeline refer to [Introducing OIDC Conformant Authentication](/api-auth/intro).
:::
-Given the user's credentials, this endpoint will authenticate the user with the provider and return a JSON object with the `access_token` and an `id_token`.
+Given the user's credentials, this endpoint will authenticate the user with the provider and return a JSON object with the Access Token and an ID Token.
### Request Parameters
@@ -79,23 +79,13 @@ Given the user's credentials, this endpoint will authenticate the user with the
| `grant_type` Required | Use the value `password` |
| `username` Required | The user's username |
| `password` Required | The user's password |
-| `scope` | Use `openid` to get an `id_token`, `openid profile email` to get an `id_token` and the user profile, or `openid offline_access` to get an `id_token` and a `refresh_token`. |
+| `scope` | Use `openid` to get an ID Token, `openid profile email` to get an ID Token and the user profile, or `openid offline_access` to get an ID Token and a Refresh Token. |
| `id_token` | Used to authenticate using a token instead of username/password, in [Touch ID](/libraries/lock-ios/touchid-authentication) scenarios. |
| `device` | You should set this to a string, if you are requesting a Refresh Token (`scope=offline_access`). |
-### Test with Authentication API Debugger
-
-<%= include('../../../_includes/_test-this-endpoint') %>
-
-1. At the *Configuration* tab, set the **Application** field to the application you want to use for the test, and **Connection** to the name of the connection to use.
-
-1. Copy the **Callback URL** and set it as part of the **Allowed Callback URLs** of your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
-1. At the *OAuth2 / OIDC* tab, set the **Username** and **Password**, and click **Resource Owner Endpoint**.
-
### Remarks
-- This endpoint only works for database connections, passwordless connections, Active Directory/LDAP, Windows Azure AD and ADFS.
+- This endpoint only works for database connections, passwordless connections, Active Directory/LDAP, Windows Azure AD and ADFS.
- The `profile` scope value requests access to the End-User's default profile Claims, which are: `name`, `family_name`, `given_name`, `middle_name`, `nickname`, `preferred_username`, `profile`, `picture`, `website`, `gender`, `birthdate`, `zoneinfo`, `locale`, and `updated_at`.
@@ -105,6 +95,6 @@ Given the user's credentials, this endpoint will authenticate the user with the
For the complete error code reference for this endpoint refer to [Errors > POST /oauth/ro](#post-oauth-ro).
-### More Information
+### Learn More
- [Calling APIs from Highly Trusted Applications](/api-auth/grant/password)
diff --git a/articles/api/authentication/legacy/_userinfo.md b/articles/api/authentication/legacy/_userinfo.md
index 25e29fce75..d35e12a99e 100644
--- a/articles/api/authentication/legacy/_userinfo.md
+++ b/articles/api/authentication/legacy/_userinfo.md
@@ -1,5 +1,6 @@
-# User Profile
+
+# User Profile
## Get Token Info
```http
@@ -73,17 +74,14 @@ webAuth.parseHash(window.location.hash, function(err, authResult) {
This endpoint is part of the legacy authentication pipeline and will be disabled for those who use our latest, OIDC conformant, pipeline. We encourage using the [/userinfo endpoint](#get-user-info) instead. For more information on the latest authentication pipeline refer to [Introducing OIDC Conformant Authentication](/api-auth/intro).
:::
-This endpoint validates a JSON Web Token (signature and expiration) and returns the user information associated with the user id `sub` property of the token.
+This endpoint validates a JSON Web Token (JWT) (signature and expiration) and returns the user information associated with the user id `sub` property of the token.
### Request Parameters
| Parameter | Description |
|:-----------------|:------------|
-| `id_token` Required | The `id_token` to use. |
-
-### Test with Postman
+| `id_token` Required | The ID Token to use. |
-<%= include('../../../_includes/_test-with-postman') %>
### Remarks
@@ -92,8 +90,8 @@ This endpoint validates a JSON Web Token (signature and expiration) and returns
- `X-RateLimit-Remaining`: Number of requests available. Each new request reduces this number by 1. For each minute that passes, requests are added back, so this number increases by 1 each time.
- `X-RateLimit-Reset`: Remaining time until the rate limit (`X-RateLimit-Limit`) resets. The value is in [UTC epoch seconds](https://en.wikipedia.org/wiki/Unix_time).
-### More Information
+### Learn More
-- [User Profile: In-Depth Details - API](/user-profile/user-profile-details#api)
+- [User Profile Struture](/users/references/user-profile-structure)
- [Auth0 API Rate Limit Policy](/policies/rate-limits)
diff --git a/articles/api/authorization-extension/_groups.md b/articles/api/authorization-extension/_groups.md
index 39262240d9..17bc41355c 100644
--- a/articles/api/authorization-extension/_groups.md
+++ b/articles/api/authorization-extension/_groups.md
@@ -69,7 +69,7 @@ Use this endpoint to retrieve all groups.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -107,11 +107,11 @@ include('../../_includes/_http-method', {
"link": "#get-single-group"
}) %>
-Use this endpoint to get a single group based on its unique identifier. Add "?expand" to also load all roles and permissions for this group.
+Use this endpoint to get a single group based on its unique identifier. Add "?expand" to also load all roles and permissions for this group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -161,7 +161,7 @@ Use this endpoint to create a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
create:groups
@@ -209,7 +209,7 @@ Use this endpoint to delete a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
delete:groups
@@ -264,7 +264,7 @@ Use this endpoint to update the name or the description of a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -309,7 +309,7 @@ Use this endpoint to retrieve the mappings of a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -326,7 +326,7 @@ The [Access Token](#get-an-access-token) should have the following scopes:
Use this endpoint to create one or more mappings in a group.
-Group Mappings allow you to dynamically "add" users to different Groups based on the users' Connections. Essentially, using the Connection and the Groups information provided by the Identity Provider, you can dynamically make the user a member of the group in which you've created the appropriate mapping. For more information, refer to [Group Mappings](/extensions/authorization-extension/v2#group-mappings).
+Group Mappings allow you to dynamically "add" users to different Groups based on the users' Connections. Essentially, using the Connection and the Groups information provided by the Identity Provider, you can dynamically make the user a member of the group in which you've created the appropriate mapping. For more information, refer to [Group Mappings](/extensions/authorization-extension/v2/implementation/setup#group-mappings).
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -414,7 +415,7 @@ Use this endpoint to delete one or more group mappings from a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -423,7 +424,7 @@ The [Access Token](#get-an-access-token) should have the following scopes:
| Parameter | Description |
|:-----------------|:------------|
| `{extension_url}` Required | The URL of your Authorization Extension. For more info, see [Find your extension URL](#find-your-extension-url) |
-| `{access_token}` Required | The token your application retrieved from Auth0 in order to access the API. For more information on how to implement this, refer to our [Client Credentials implementation guide](/api-auth/tutorials/client-credentials) |
+| `{access_token}` Required | The token your application retrieved from Auth0 in order to access the API. For more information on how to implement this, refer to our [machine-to-machine flow implementation guide](/flows/guides/client-credentials/call-api-client-credentials) |
| `{group_id}` Required | The id of the group whose mappings you want to delete |
## Get Group Members
@@ -488,7 +489,7 @@ Use this endpoint to get the members for a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -499,6 +500,9 @@ The [Access Token](#get-an-access-token) should have the following scopes:
| `{extension_url}` Required | The URL of your Authorization Extension. For more info, see [Find your extension URL](#find-your-extension-url) |
| `{access_token}` Required | The token your application retrieved from Auth0 in order to access the API. For more info, see [Get an Access Token](#get-an-access-token) |
| `{group_id}` Required | The id of the group whose members you want to retrieve |
+| `{page}` | The page number. One-based. |
+| `{per_page}` | The amount of entries per page. Default: `25`. Max value: `25`. |
+
## Add Group Members
@@ -537,7 +541,7 @@ Use this endpoint to add one or more members in a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -587,7 +591,7 @@ Use this endpoint to remove one or more members from a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -643,7 +647,7 @@ Use this endpoint to get the nested members for a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -654,6 +658,8 @@ The [Access Token](#get-an-access-token) should have the following scopes:
| `{extension_url}` Required | The URL of your Authorization Extension. For more info, see [Find your extension URL](#find-your-extension-url) |
| `{access_token}` Required | The token your application retrieved from Auth0 in order to access the API. For more info, see [Get an Access Token](#get-an-access-token) |
| `{group_id}` Required | The id of the group from which the nested members will be retrieved |
+| `{page}` | The page number. One-based. |
+| `{per_page}` | The amount of entries per page. Default: `25`. Max value: `25`. |
## Get Nested Groups
@@ -691,7 +697,7 @@ Use this endpoint to get the nested groups for a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -741,7 +747,7 @@ Use this endpoint to add nested groups.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -791,7 +797,7 @@ Use this endpoint to remove one or more nested groups.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -842,7 +848,7 @@ Use this endpoint to get the roles for a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -891,7 +897,7 @@ Use this endpoint to add roles to a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -941,7 +947,7 @@ Use this endpoint to remove one or more groups roles.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -1019,7 +1025,7 @@ Use this endpoint to get the nested roles for a group.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
diff --git a/articles/api/authorization-extension/_introduction.md b/articles/api/authorization-extension/_introduction.md
index 91da48ec9a..973481dac2 100644
--- a/articles/api/authorization-extension/_introduction.md
+++ b/articles/api/authorization-extension/_introduction.md
@@ -2,12 +2,12 @@
The Authorization Extension API enables you to:
-- automate provisioning for your users, roles, groups, and permissions
+- automate provisioning for your users, roles, groups, and permissions
- query the authorization context of your users in real time
-In order to use it you first have to [enable API access](/extensions/authorization-extension/v2#enable-api-access) from your Authorization Dashboard.
+In order to use it, you first have to [enable API access](/extensions/authorization-extension/v2#enable-api-access) from your Authorization Dashboard.
-For more information on the Authorization Extension and how to configure it refer to [Auth0 Authorization Extension](/extensions/authorization-extension).
+For more information on the Authorization Extension and how to configure it, refer to [Auth0 Authorization Extension](/extensions/authorization-extension).
For each endpoint in this explorer, you will find sample snippets you can use, in three available formats:
@@ -15,9 +15,11 @@ For each endpoint in this explorer, you will find sample snippets you can use, i
- Curl command
- JavaScript: depending on the endpoint each snippet may use Node.js or simple JavaScript
+Each request should be sent with a Content-Type of `application/json`.
+
## Find your extension URL
-All endpoints in this explorer, start with `https://{extension_url}`. This is the URL of your Authorization Dashboard. It differs based on you tenant's region:
+All endpoints in this explorer start with `https://{extension_url}`. This is the URL of your Authorization Dashboard. It differs based on you tenant's region:
<%
var urlUS = 'https://' + account.tenant + '.us.webtask.io/adf6e2f2b84784b57522e3b19dfc9201/api';
@@ -35,15 +37,15 @@ All endpoints in this explorer, start with `https://{extension_url}`. This is th
When you [enabled API access for your tenant](/extensions/authorization-extension/v2#enable-api-access), an API was created at your [dashboard](${manage_url}), which you can use to access the Authorization Extension API.
-To do so you will have to configure a machine to machine application which will have access to this API and which you will use to get an [Access Token](/tokens/access-token).
+To do so you will have to configure a machine to machine application which will have access to this API and which you will use to get an Access Token.
-Follow these steps to setup your application (you will have to do this only once):
+Follow these steps to set up your application (you will have to do this only once):
1. Go to [Dashboard > Applications](${manage_url}/#/applications) and create a new application of type `Machine to Machine`.
2. Go to the [Dashboard > APIs](${manage_url}/#/apis) and select the `auth0-authorization-extension-api`.
3. Go to the `Machine to Machine Applications` tab, find the application you created at the first step, and toggle the `Unauthorized` to `Authorized`.
-4. Select the [scopes](/scopes#api-scopes) that should be granted to your application, based on the endpoints you want to access. For example, `read:users` to [get all users](#get-all-users).
+4. Select the [scopes](/scopes/current/api-scopes) that should be granted to your application, based on the endpoints you want to access. For example, `read:users` to [get all users](#get-all-users).
-In order to get an `access_token` you need to `POST` to the `/oauth/token` endpoint. You can find detailed instructions [here](/api-auth/tutorials/client-credentials#ask-for-a-token).
+To get an Access Token, you need to `POST` to the `/oauth/token` endpoint. You can find detailed instructions [here](/flows/guides/client-credentials/call-api-client-credentials#request-token).
-Use this `access_token` to access the Authorization Extension API.
\ No newline at end of file
+Use this Access Token to access the Authorization Extension API.
diff --git a/articles/api/authorization-extension/_permissions.md b/articles/api/authorization-extension/_permissions.md
index d09449bd42..8c1c151fcf 100644
--- a/articles/api/authorization-extension/_permissions.md
+++ b/articles/api/authorization-extension/_permissions.md
@@ -1,6 +1,6 @@
# Permissions
-Permissions are actions or functions that a user, or group of user, is allowed to do. For example, let's say that you have an application that allows employees to enter in company expenses. You want all employees to be able to submit expenses, but want certain Finance users to have more admin type of actions such as being able to approve or delete expenses. These actions can be mapped to [permissions](/extensions/authorization-extension#permissions) (which later on can be grouped in [roles](/extensions/authorization-extension#roles)):
+Permissions are actions or functions that a user, or group of user, is allowed to do. For example, let's say that you have an application that allows employees to enter in company expenses. You want all employees to be able to submit expenses, but want certain Finance users to have more admin type of actions such as being able to approve or delete expenses. These actions can be mapped to [permissions](/extensions/authorization-extension#permissions) (which later on can be grouped in [roles](/extensions/authorization-extension#roles)):
For more information, refer to [Auth0 Authorization Extension](/extensions/authorization-extension#permissions).
@@ -41,7 +41,7 @@ Use this endpoint to retrieve all permissions.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:permissions
@@ -83,7 +83,7 @@ Use this endpoint to get a single permission based on its unique identifier.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:permissions
@@ -134,7 +134,7 @@ Use this endpoint to create a permission.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
create:permissions
@@ -193,7 +193,7 @@ Use this endpoint to update the details of a permission.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:permissions
@@ -243,7 +243,7 @@ Use this endpoint to remove a permission.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
delete:permissions
diff --git a/articles/api/authorization-extension/_roles.md b/articles/api/authorization-extension/_roles.md
index 172a23447d..45ca6b2d8c 100644
--- a/articles/api/authorization-extension/_roles.md
+++ b/articles/api/authorization-extension/_roles.md
@@ -1,6 +1,6 @@
# Roles
-Roles are collections of permissions. For example, let's say that you have an application that allows employees to enter in company expenses. You want all employees to be able to submit expenses, but want certain Finance users to have more admin type of actions such as being able to approve or delete expenses. These actions can be mapped to [Permissions](/extensions/authorization-extension#permissions) and then assigned to a certain role.
+Roles are collections of permissions. For example, let's say that you have an application that allows employees to enter in company expenses. You want all employees to be able to submit expenses, but want certain Finance users to have more admin type of actions such as being able to approve or delete expenses. These actions can be mapped to [Permissions](/extensions/authorization-extension#permissions) and then assigned to a certain role.
For more information, refer to [Auth0 Authorization Extension](/extensions/authorization-extension#roles).
@@ -54,7 +54,7 @@ Use this endpoint to retrieve all roles.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:roles
@@ -96,7 +96,7 @@ Use this endpoint to get a single role based on its unique identifier.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:roles
@@ -150,7 +150,7 @@ Use this endpoint to create a role.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
create:roles
@@ -217,7 +217,7 @@ Use this endpoint to update the details of a role.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:roles
@@ -268,7 +268,7 @@ Use this endpoint to remove a role.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
delete:roles
diff --git a/articles/api/authorization-extension/_users.md b/articles/api/authorization-extension/_users.md
index 7916708817..a2337dd9f2 100644
--- a/articles/api/authorization-extension/_users.md
+++ b/articles/api/authorization-extension/_users.md
@@ -1,6 +1,6 @@
# Users
-These endpoints enable you to manage all the current users of your applications. You can retrieve their profile and edit or view their groups and their roles.
+These endpoints enable you to manage all the current users of your applications. You can retrieve their profile and edit or view their groups and their roles.
For more information, refer to [Auth0 Authorization Extension](/extensions/authorization-extension/v2#users).
@@ -32,7 +32,7 @@ GET https://{extension_url}/users
],
"user_id":"auth0|59091da1b3c34a15589c780d",
"last_login":"2017-06-25T07:28:54.719Z",
- "name":"dummy.user@example.com",
+ "name":"placeholder.user@example.com",
"picture":"https://s.gravatar.com/avatar/your-gravatar.png",
"email":"richard.dowinton@auth0.com"
}
@@ -53,7 +53,7 @@ Use this endpoint to retrieve all users.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:users
@@ -63,6 +63,8 @@ The [Access Token](#get-an-access-token) should have the following scopes:
|:-----------------|:------------|
| `{extension_url}` Required | The URL of your Authorization Extension. For more info, see [Find your extension URL](#find-your-extension-url) |
| `{access_token}` Required | The token your client retrieved from Auth0 in order to access the API. For more info, see [Get an Access Token](#get-an-access-token) |
+| `{page}` | The page number. One-based. |
+| `{per_page}` | The amount of entries per page. Default: `100`. Max value: `200`. |
## Get a single User
@@ -76,11 +78,11 @@ GET https://{extension_url}/users/{user_id}
```text
{
- "email":"dummy.user@example.com",
+ "email":"placeholder.user@example.com",
"email_verified":true,
"user_id":"auth0|59091da1b3c34a15589c780d",
"picture":"https://s.gravatar.com/avatar/your-gravatar.png",
- "nickname":"dummy.user",
+ "nickname":"placeholder.user",
"identities":[
{
"user_id":"59091da1b3c34a15589c780d",
@@ -91,7 +93,7 @@ GET https://{extension_url}/users/{user_id}
],
"updated_at":"2017-06-25T07:28:54.719Z",
"created_at":"2017-06-08T15:30:41.237Z",
- "name":"dummy.user@example.com",
+ "name":"placeholder.user@example.com",
"app_metadata":{
"authorization":{
"roles":[
@@ -121,7 +123,7 @@ Use this endpoint to get a single user based on its unique identifier.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:users
@@ -171,7 +173,7 @@ Use this endpoint to get the groups of a single user, based on its unique identi
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:users
@@ -217,11 +219,11 @@ include('../../_includes/_http-method', {
"link": "#add-user-to-groups"
}) %>
-Use this endpoint to add one or more users in a group.
+Use this endpoint to add a user to one or more groups.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:groups
@@ -272,7 +274,7 @@ Use this endpoint to calculate the group memberships for a user (including neste
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:groups
@@ -324,7 +326,7 @@ Use this endpoint to get the roles of a single user, based on its unique identif
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:users
@@ -374,7 +376,7 @@ Use this endpoint to assign a role to a user.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:users
@@ -412,7 +414,7 @@ curl --request DELETE \
(empty response body)
```
-<% var path = '/users/{role_id}/roles'; %>
+<% var path = '/users/{user_id}/roles'; %>
<%=
include('../../_includes/_http-method', {
"http_badge": "badge-danger",
@@ -425,7 +427,7 @@ Use this endpoint to remove one or more user from a role.
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
update:roles
@@ -436,7 +438,7 @@ The [Access Token](#get-an-access-token) should have the following scopes:
| `{extension_url}` Required | The URL of your Authorization Extension. For more info, see [Find your extension URL](#find-your-extension-url) |
| `{access_token}` Required | The token your client retrieved from Auth0 in order to access the API. For more info, see [Get an Access Token](#get-an-access-token) |
| `{user_id}` Required | The id of the user you want to remove from roles |
-| `{role_id}` Required | The id of the role(s) you want to remove users from |
+| `body` Required | The id of the role(s) you want to remove users from (i.e. `[ "{role_id}" ]`) |
## Calculate Roles
@@ -478,7 +480,7 @@ Use this endpoint to calculate the roles assigned to the user (including through
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:roles
@@ -537,7 +539,7 @@ Use this endpoint to execute the authorization policy for a user in the context
### Scopes
-The [Access Token](#get-an-access-token) should have the following scopes:
+The [Access Token](#get-an-access-token) should have the following scopes:
read:users
@@ -546,8 +548,8 @@ The [Access Token](#get-an-access-token) should have the following scopes:
| Parameter | Description |
|:-----------------|:------------|
| `{extension_url}` Required | The URL of your Authorization Extension. For more info, see [Find your extension URL](#find-your-extension-url) |
-| `{access_token}` Required | The token your client retrieved from Auth0 in order to access the API. For more info, see [Get an Access Token](#get-an-access-token) |
+| `{access_token}` Required | The token your client retrieved from Auth0 to access the API. For more info, see [Get an Access Token](#get-an-access-token) |
| `{user_id}` Required | |
| `{client_id}` Required | |
-| `connectionName` | The connection name the user logged in with |
+| `connectionName` Required | The name of the connection with which the user logged in |
| `groups` | List of group names received from the IdP (AD, ADFS, and so on) |
diff --git a/articles/api/authorization-extension/index.md b/articles/api/authorization-extension/index.md
index f538ea6210..cc27f2407b 100644
--- a/articles/api/authorization-extension/index.md
+++ b/articles/api/authorization-extension/index.md
@@ -1,6 +1,14 @@
---
title: Authorization Extension API Explorer
fullWidth: true
+topics:
+ - authorization
+ - apis
+ - api-authorization
+contentType:
+ - reference
+ - index
+useCase: invoke-api
---
diff --git a/articles/api/info.md b/articles/api/info.md
index 7e2b196133..44920523b6 100644
--- a/articles/api/info.md
+++ b/articles/api/info.md
@@ -1,24 +1,31 @@
---
-description: This page explains the basics of Auth0's Management and Authentication APIs.
+title: Auth0 APIs
+description: Learn about Auth0's Management and Authentication APIs.
section: apis
crews: crew-2
+topics:
+ - management-api
+ - authorization-api
+ - apis
+contentType: reference
+useCase: invoke-api
---
-
# Auth0 APIs
-Auth0 exposes two APIs for developers to consume in their applications:
+Auth0 exposes the following APIs for developers to consume in their applications.
+
+## Authentication API
-* **Authentication**: Handles identity-related tasks;
-* **Management**: Handles management of your Auth0 account, including functions related to (but not limited to):
+The Authentication API exposes identity functionality for Auth0 and supported identity protocols (including OpenID Connect, OAuth, and SAML).
- * Applications;
- * Connections;
- * Emails;
- * Users.
+Typically, you should consume this API through one of the Auth0 SDKs, such as [Auth0.js](/libraries/auth0js), or a library like [Lock](/libraries/lock). However, if you are building your authentication UI manually, you will need to call the Authentication API directly.
-## Authentication API
+Some example tasks include:
-The Authentication API exposes Auth0 identity functionality, as well as those of supported identity protocols (such as OpenID Connect, OAuth, and SAML). Typically, you would consume this API through one of the Auth0 SDKs, such as [Auth0.js](/libraries/auth0js), or a library, like [Lock](/libraries/lock). If you are building your authentication UI manually, you would need to interface directly with the Authentication API.
+* Get [tokens](/tokens) during authentication
+* Request a user's profile using an [Access Token](/tokens/concepts/access-tokens)
+* Exchange [Refresh Tokens](/tokens/concepts/refresh-tokens) for new Access Tokens
+* Request a challenge for [multi-factor authentication (MFA)](/mfa)
@@ -28,7 +35,7 @@ The Authentication API exposes Auth0 identity functionality, as well as those of
API Explorer
-
Learn about and use the Auth0 Authentication API in the browser.
+
Explore the requests and responses for Auth0 Authentication API endpoints in your browser.
@@ -46,9 +53,16 @@ The Authentication API exposes Auth0 identity functionality, as well as those of
-## Management API v2
+## Management API
-The Management API allows you to manage every aspect of your Auth0 account. For example, you can use the Management API to automate the configuration of your user environments or for runtime tasks such as user creation.
+The Management API allows you to manage your Auth0 account programmatically, so you can automate configuration of your environment. Most of the tasks you can perform in the Auth0 Management Dashboard can also be performed programmatically by using this API.
+
+Some example tasks include:
+
+* Register your applications and APIs with Auth0
+* Set up [connections](/connections) with which your users can authenticate
+* [Manage users](/users)
+* [Link user accounts](/users/guides/link-user-accounts)
@@ -67,7 +81,7 @@ The Management API allows you to manage every aspect of your Auth0 account. For
@@ -76,6 +90,10 @@ The Management API allows you to manage every aspect of your Auth0 account. For
-### Management API v1 - DEPRECATED
+### Management API v1 has been deprecated
+
+The Management API v1 is deprecated and should not be used for new projects.
+
+Management API v1 will reach its End of Life on **July 13, 2020**. You may be required to take action before that date to ensure no interruption to your service. See [Migrate from Management API v1 to v2](/migrations/guides/management-api-v1-v2) for details. Notifications have been and will continue to be sent to customers that need to complete this migration.
-The Management API v1 is deprecated and **should not** be used for new projects. If your existing application uses Management API v1, you can reference its API explorer [here](/api/v1).
+If your existing application still uses Management API v1, see [Management API v1](/api/management/v1) noting that some endpoints may have limited functionality.
\ No newline at end of file
diff --git a/articles/api/management/guides/apis/enable-rbac.md b/articles/api/management/guides/apis/enable-rbac.md
new file mode 100644
index 0000000000..3c9258dbe9
--- /dev/null
+++ b/articles/api/management/guides/apis/enable-rbac.md
@@ -0,0 +1,58 @@
+---
+title: Enable Role-Based Access Control for APIs
+description: Learn how to enable role-based access control (RBAC) for an API using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - roles
+ - rbac
+ - apis
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Enable Role-Based Access Control for APIs
+
+This guide will show you how to enable [role-based access control (RBAC)](/authorization/concepts/rbac) using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/apis/enable-rbac). This effectively enables the API Authorization Core feature set.
+
+1. Make a `PATCH` call to the [Update Resource Server endpoint](/api/management/v2#!/resource_servers/patch_resource_server). Be sure to replace `API_ID`, `MGMT_API_ACCESS_TOKEN`, `PERMISSION_NAME`, and `PERMISSION_DESC` placeholder values with your API ID, Management API Access Token, permission name(s), and permission description(s), respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/resource-servers/API_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"enforce_policies\": \"true\", \"token_dialect\": \"TOKEN_DIALECT\" }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `API_ID` | Τhe ID of the API for which you want to enable RBAC. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:resource_servers`. |
+| `TOKEN_DIALECT` | Dialect of the Access Token for the specified API.|
+
+## Token Dialect Options
+
+Available options include:
+
+| Value | Description |
+|-------|-------------|
+| `access_token` | In the `scope` claim of the Access Token, includes an intersection of the requested permissions and the permissions assigned to the user. No `permissions` claim is passed. |
+| `access_token_authz` | In the `scope` claim of the Access Token, includes an intersection of the requested permissions and the permissions assigned to the user. In the `permissions` claim of the Access Token, includes all permissions assigned to the user. Allows you to make minimal calls to retrieve permissions, but increases token size. |
+
+When RBAC is _disabled_, default behavior is observed; an application can request any permission defined for the API, and the `scope` claim will include all requested permissions.
+
+::: warning
+Remember that any configured [rules](/authorization/concepts/authz-rules) run _after_ the RBAC-based authorization decisions are made, so they may override default behavior.
+:::
diff --git a/articles/api/management/guides/apis/update-permissions-apis.md b/articles/api/management/guides/apis/update-permissions-apis.md
new file mode 100644
index 0000000000..7d39e4ca0c
--- /dev/null
+++ b/articles/api/management/guides/apis/update-permissions-apis.md
@@ -0,0 +1,52 @@
+---
+title: Update API Permissions
+description: Learn how to update permissions for APIs using the Auth0 Management API.
+topics:
+ - authorization
+ - mgmt-api
+ - RBAC
+ - scopes
+ - permissions
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Update API Permissions
+
+This guide will show you how to update permissions for an API using Auth0's Management API. This task can also be performed using the Dashboard, but first you will need to [delete the permission](/dashboard/guides/apis/delete-permissions-apis) and then [add the permission](/dashboard/guides/roles/apis/add-permissions-apis) again.
+
+::: warning
+By default, any user of any application can ask for any permission defined here. You can implement access policies to limit this behavior via [Rules](/rules).
+:::
+
+::: note
+Patching the permissions with an empty object removes the permissions completely.
+:::
+
+1. Make a `PATCH` call to the [Update Resource Server endpoint](/api/management/v2#!/resource_servers/patch_resource_server). Be sure to replace `API_ID`, `MGMT_API_ACCESS_TOKEN`, `PERMISSION_NAME`, and `PERMISSION_DESC` placeholder values with your API ID, Management API Access Token, permission name(s), and permission description(s), respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/resource-servers/API_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"scopes\": [ { \"value\": \"PERMISSION_NAME\", \"description\": \"PERMISSION_DESC\" }, { \"value\": \"PERMISSION_NAME\", \"description\": \"PERMISSION_DESC\" } ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `API_ID` | Τhe ID of the API for which you want to add permissions. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:resource_servers`. |
+| `PERMISSION_NAME` | Name(s) of the permission(s) you would like to add for the specified API. |
+| `PERMISSION_DESC` | User-friendly description(s) of the permission(s) you would like to add for the specified API. |
\ No newline at end of file
diff --git a/articles/api/management/guides/applications/remove-app.md b/articles/api/management/guides/applications/remove-app.md
new file mode 100644
index 0000000000..9e10014666
--- /dev/null
+++ b/articles/api/management/guides/applications/remove-app.md
@@ -0,0 +1,34 @@
+---
+title: Remove Application
+description: Learn how to remove an Auth0-registered application using the Auth0 Management API.
+toc: false
+topics:
+ - applications
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - call-api
+---
+# Remove Application
+
+This guide will show you how to remove an application using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/applications/remove-app).
+
+1. Make a `DELETE` call to the [Delete a Client endpoint](/api/management/v2#!/Clients/delete_clients_by_id). Be sure to replace `YOUR_CLIENT_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your client ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "DELETE",
+ "url": "https://${account.namespace}/api/v2/clients/YOUR_CLIENT_ID",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| Value | Description |
+| - | - |
+| `YOUR_CLIENT_ID` | Τhe ID of the application to be deleted. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `delete:clients`. |
diff --git a/articles/api/management/guides/applications/rotate-client-secret.md b/articles/api/management/guides/applications/rotate-client-secret.md
new file mode 100644
index 0000000000..464308df41
--- /dev/null
+++ b/articles/api/management/guides/applications/rotate-client-secret.md
@@ -0,0 +1,42 @@
+---
+title: Rotate Client Secret
+description: Learn how to change your application's client secret using the Auth0 Management API.
+topics:
+ - applications
+ - client-secrets
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# Rotate Client Secret
+
+This guide will show you how to change your application's client secret using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/applications/rotate-client-secret).
+
+::: warning
+New secrets may be delayed while rotating. To minimize downtime, we suggest you store the new client secret in your application's code as a fallback to the previous secret. This way, if the connection doesn't work with the old secret, your app will use the new secret.
+
+Secrets can be stored in a list (or similar structure) until they're no longer needed. Once you're sure that an old secret is obsolete, you can remove its value from your app's code.
+:::
+
+1. Make a `POST` call to the [Rotate a Client Secret endpoint](/api/management/v2#!/Clients/post_rotate_secret). Be sure to replace `YOUR_CLIENT_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your client ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/clients/YOUR_CLIENT_ID/rotate-secret",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| Value | Description |
+| - | - |
+| `YOUR_CLIENT_ID` | Τhe ID of the application to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `update:client_keys`. |
+
+2. Update authorized applications
+
+When you rotate a client secret, you must update any authorized applications with the new value.
diff --git a/articles/api/management/guides/applications/update-grant-types.md b/articles/api/management/guides/applications/update-grant-types.md
new file mode 100644
index 0000000000..febf502d5a
--- /dev/null
+++ b/articles/api/management/guides/applications/update-grant-types.md
@@ -0,0 +1,51 @@
+---
+title: Update Grant Types
+description: Learn how to update an application's grant types using Auth0's Management API.
+topics:
+ - applications
+ - grant-types
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# Update Grant Types
+
+This guide will show you how to change your application's grant types using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/applications/update-grant-types).
+
+::: warning
+As of 8 June 2017, new Auth0 customers **cannot** add legacy grant types to their Applications. Customers as of 8 June 2017 can add legacy grant types to only their existing Applications.
+:::
+
+::: warning
+Attempting to use a flow with an Application lacking the appropriate `grant_types` for that flow (or with the field empty) will result in the following error:
+
+```text
+Grant type `grant_type` not allowed for the client.
+```
+:::
+
+1. Make a `PATCH` call to the [Update a Client endpoint](/api/management/v2#!/Clients/patch_clients_by_id). Be sure to replace `YOUR_CLIENT_ID`, `MGMT_API_ACCESS_TOKEN`, and `GRANT_TYPE` placeholder values with your client ID, Management API Access Token, and desired grant type, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/clients/YOUR_CLIENT_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"grant_types\": \"GRANT_TYPES\" }"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `YOUR_CLIENT_ID` | Τhe ID of the application to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `update:clients`. |
+| `GRANT_TYPES` | The grant types you would like to enable for the specified application. |
diff --git a/articles/api/management/guides/applications/update-ownership.md b/articles/api/management/guides/applications/update-ownership.md
new file mode 100644
index 0000000000..bbe9d019bf
--- /dev/null
+++ b/articles/api/management/guides/applications/update-ownership.md
@@ -0,0 +1,40 @@
+---
+title: Update Application Ownership
+description: Learn how to update application ownership using the Auth0 Management API. This will let you specify whether an application is registered with Auth0 as a first-party or third-party application.
+toc: true
+topics:
+ - applications
+ - application-types
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# Update Application Ownership
+
+This guide will show you how to use Auth0's Management API to update application ownership, which allows you to specify whether an application is registered with Auth0 as a first-party or third-party application.
+
+Make a `PATCH` call to the [Update a Client endpoint](/api/management/v2#!/Clients/patch_clients_by_id). Be sure to replace `YOUR_CLIENT_ID`,`MGMT_API_ACCESS_TOKEN`, and `OWNERSHIP_BOOLEAN` placeholder values with your client ID, Management API Access Token, and boolean representing the application's ownership, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/clients/YOUR_CLIENT_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"is_first_party\": \"OWNERSHIP_BOOLEAN\" }"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `YOUR_CLIENT_ID` | Τhe ID of the application to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `update:clients`. |
+| `OWNERSHIP_BOOLEAN` | The ownership you would like to specify for the application. If the application is first-party, `is_first_party` should have a value of `true`. If the application is third-party, `is_first_party` should have a value of `false`. |
diff --git a/articles/api/management/guides/applications/view-ownership.md b/articles/api/management/guides/applications/view-ownership.md
new file mode 100644
index 0000000000..58d736a93a
--- /dev/null
+++ b/articles/api/management/guides/applications/view-ownership.md
@@ -0,0 +1,35 @@
+---
+title: View Application Ownership
+description: Learn how to check whether an application is registered with Auth0 as a first-party or third-party app using the Auth0 Management API.
+toc: true
+topics:
+ - applications
+ - application-types
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# View Application Ownership
+
+This guide will show you how to use Auth0's Management API to check whether an application is registered with Auth0 as a first-party or third-party application.
+
+1. Make a `GET` call to the [Get a Client endpoint](/api/management/v2#!/Clients/get_clients_by_id). Be sure to replace `YOUR_CLIENT_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your client ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/clients/YOUR_CLIENT_ID?fields=is_first_party&include_fields=true",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| Value | Description |
+| - | - |
+| `YOUR_CLIENT_ID` | Τhe ID of the application to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `read:clients`. |
+
+If the application is first-party, the `is_first_party` field will have a value of `true`. If the application is third-party, the `is_first_party` field will have a value of `false`.
diff --git a/articles/api/management/guides/connections/configure-connection-sync.md b/articles/api/management/guides/connections/configure-connection-sync.md
new file mode 100644
index 0000000000..c3343c830c
--- /dev/null
+++ b/articles/api/management/guides/connections/configure-connection-sync.md
@@ -0,0 +1,46 @@
+---
+title: Configure Connection Sync with Auth0
+description: Learn how to update connection preferences for an upstream identity provider to control when updates to user profile root attributes will be allowed using the Auth0 Management API.
+topics:
+ - connections
+ - identity-providers
+ - user-profile
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+ - manage-users
+---
+# Configure Connection Sync with Auth0
+
+This guide will show you how to update connection preferences for an upstream [Identity Provider](/connections) to control when updates to user profile root attributes will be allowed using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/connections/configure-connection-sync).
+
+::: warning
+Before completing this step, you should first [retrieve the existing values of the connection's `options` object](/api/management/guides/connections/retrieve-connection-options) to avoid overriding the current values. If you do not, any missing parameters from the original object will be lost after you update.
+:::
+
+1. Make a `PATCH` call to the [Update a Connection endpoint](/api/management/v2#!/Connections/patch_connections_by_id). Make sure you include the original options values in the call to avoid overriding the current values. Also, be sure to replace `CONNECTION_ID`, `MGMT_API_ACCESS_TOKEN`, and `ATTRIBUTE_UPDATE_VALUE` placeholder values with your connection ID, Management API Access Token, and attribute update value, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/connections/CONNECTION_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"options\":{\"set_user_root_attributes\": \"ATTRIBUTE_UPDATE_VALUE\"}}"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `CONNECTION_ID` | ID of the connection for which you want to allow updates to root attributes. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:connections`. |
+| `ATTRIBUTE_UPDATE_VALUE` | Indicates when you want to allow updates to user profile root attributes. Valid values are `on_first_login` and `on_each_login`. Defaults to `on_each_login` for new connections. |
\ No newline at end of file
diff --git a/articles/api/management/guides/connections/promote-connection-domain-level.md b/articles/api/management/guides/connections/promote-connection-domain-level.md
new file mode 100644
index 0000000000..50c1c6f4bc
--- /dev/null
+++ b/articles/api/management/guides/connections/promote-connection-domain-level.md
@@ -0,0 +1,39 @@
+---
+title: Promote Connection to Domain Level
+description: Learn how to promote a connection to domain level using the Auth0 Management API.
+topics:
+ - connections
+ - third-party-app
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Promote Connection to Domain Level
+
+This guide will show you how to promote connections to domain level using Auth0's Management API.
+
+1. Make a `PATCH` call to the [Update a Connection endpoint](/api/management/v2#!/Connections/patch_connections_by_id). Be sure to replace `CONNECTION_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your connection ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/connections/CONNECTION_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"is_domain_connection\": true }"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `CONNECTION_ID` | Τhe ID of the connection to be promoted. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:connections`. |
\ No newline at end of file
diff --git a/articles/api/management/guides/connections/retrieve-connection-options.md b/articles/api/management/guides/connections/retrieve-connection-options.md
new file mode 100644
index 0000000000..1d62b08e31
--- /dev/null
+++ b/articles/api/management/guides/connections/retrieve-connection-options.md
@@ -0,0 +1,32 @@
+---
+title: Retrieve Connection Options
+description: Learn how to retrieve the options object for a connection using the Auth0 Management API.
+topics:
+ - connections
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Retrieve Connection Options
+
+This guide will show you how to retrieve the options object for a [connection](/connections) using Auth0's Management API.
+
+1. Make a `GET` call to the [Get Connection endpoint](/api/management/v2#!/Connections/get_connections_by_id). Be sure to replace `CONNECTION_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your connection ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/connections/CONNECTION-ID?fields=options",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| Value | Description |
+| - | - |
+| `CONNECTION_ID` | Τhe ID of the connection for which you want to retrieve the `options` object. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `read:connections`. |
diff --git a/articles/api/management/guides/roles/add-permissions-roles.md b/articles/api/management/guides/roles/add-permissions-roles.md
new file mode 100644
index 0000000000..5c9ce675be
--- /dev/null
+++ b/articles/api/management/guides/roles/add-permissions-roles.md
@@ -0,0 +1,45 @@
+---
+title: Add Permissions to Roles
+description: Learn how to add permissions to roles for Auth0's API Authorization Core feature using the Auth0 Management API.
+topics:
+ - authorization
+ - mgmt-api
+ - roles
+ - permissions
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Add Permissions to Roles
+
+This guide will show you how to add permissions to [roles](/authorization/concepts/rbac) using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/roles/add-permissions-roles). The roles and their permissions can be used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `POST` call to the [Add Role Permissions endpoint](/api/management/v2#!/Roles/post_role_permission_assignment). Be sure to replace `ROLE_ID`, `MGMT_API_ACCESS_TOKEN`, `API_IDENTIFIER`, and `PERMISSION_NAME` placeholder values with your role ID, Management API Access Token, API identifier (audience), and permission name(s), respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/roles/ROLE_ID/permissions",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"permissions\": [ { \"resource_server_identifier\": \"API_IDENTIFIER\", \"permission_name\": \"PERMISSION_NAME\" }, { \"resource_server_identifier\": \"API_IDENTIFIER\", \"permission_name\": \"PERMISSION_NAME\" } ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `ROLE_ID` | Τhe ID of the role for which you want to add permissions. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:roles`. |
+| `API_IDENTIFIER` | This is the identifier of the API associated with the permission(s) you would like to add for the specified role, otherwise known as the audience. This is not the API ID. |
+| `PERMISSION_NAME` | Name(s) of the permission(s) you would like to add for the specified role. |
diff --git a/articles/api/management/guides/roles/create-roles.md b/articles/api/management/guides/roles/create-roles.md
new file mode 100644
index 0000000000..3208506c22
--- /dev/null
+++ b/articles/api/management/guides/roles/create-roles.md
@@ -0,0 +1,44 @@
+---
+title: Create Roles
+description: Learn how to create a role using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - roles
+ - rbac
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Create Roles
+
+This guide will show you how to create [roles](/authorization/concepts/rbac) using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/roles/create-roles). The roles can be used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `POST` call to the [Create Role endpoint](/api/management/v2#!/Roles/post_roles). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `ROLE_NAME`, and `ROLE_DESC` placeholder values with your Management API Access Token, role name, and role description, respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/roles",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"name\": \"ROLE_NAME\", \"description\": \"ROLE_DESC\" }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:roles`. |
+| `ROLE_NAME` | Name of the role you would like to create. |
+| `ROLE_DESC` | User-friendly description of the role. |
\ No newline at end of file
diff --git a/articles/api/management/guides/roles/delete-roles.md b/articles/api/management/guides/roles/delete-roles.md
new file mode 100644
index 0000000000..28396f3025
--- /dev/null
+++ b/articles/api/management/guides/roles/delete-roles.md
@@ -0,0 +1,37 @@
+---
+title: Delete Roles
+description: Learn how to delete a role using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Delete Roles
+
+This guide will show you how to delete a [role](/authorization/concepts/rbac) using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/roles/delete-roles). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `DELETE` call to the [Delete Role endpoint](/api/management/v2#!/Roles/delete_roles_by_id). Be sure to replace `ROLE_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your role ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "DELETE",
+ "url": "https://${account.namespace}/api/v2/roles/ROLE_ID",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `ROLE_ID` | Τhe ID of the role you want to delete. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `delete:roles`. |
\ No newline at end of file
diff --git a/articles/api/management/guides/roles/edit-role-definitions.md b/articles/api/management/guides/roles/edit-role-definitions.md
new file mode 100644
index 0000000000..676490c389
--- /dev/null
+++ b/articles/api/management/guides/roles/edit-role-definitions.md
@@ -0,0 +1,45 @@
+---
+title: Edit Role Definitions
+description: Learn how to edit a role definition using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Edit Role Definitions
+
+This guide will show you how to edit a [role](/authorization/concepts/rbac) definition using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/roles/edit-role-definitions). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `PATCH` call to the [Update Role endpoint](/api/management/v2#!/Roles/patch_roles_by_id). Be sure to replace `ROLE_ID`, `MGMT_API_ACCESS_TOKEN`, `ROLE_NAME`, and `ROLE_DESC` placeholder values with your role ID, Management API Access Token, role name, and role description, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/roles/ROLE_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"name\": \"ROLE_NAME\", \"description\": \"ROLE_DESC\" }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `ROLE_ID` | Τhe ID of the role for which you want to edit the definition. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:roles`. |
+| `ROLE_NAME` | Name of the role. |
+| `ROLE_DESC` | User-friendly description of the role. |
\ No newline at end of file
diff --git a/articles/api/management/guides/roles/remove-role-permissions.md b/articles/api/management/guides/roles/remove-role-permissions.md
new file mode 100644
index 0000000000..1bb761e434
--- /dev/null
+++ b/articles/api/management/guides/roles/remove-role-permissions.md
@@ -0,0 +1,45 @@
+---
+title: Remove Permissions from Roles
+description: Learn how to remove permissions added to a role using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Remove Permissions from Roles
+
+This guide will show you how to remove the [permissions](/authorization/concepts/rbac) assigned to a role using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/roles/remove-role-permissions). The assigned permissions and roles are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `DELETE` call to the [Delete Role Permissions endpoint](/api/management/v2#!/Roles/delete_role_permission_assignment). Be sure to replace `ROLE_ID`, `MGMT_API_ACCESS_TOKEN`, `API_ID`, and `PERMISSION_NAME` placeholder values with your role ID, Management API Access Token, API ID(s), and permission name(s), respectively.
+
+```har
+{
+ "method": "DELETE",
+ "url": "https://${account.namespace}/api/v2/roles/ROLE_ID/permissions",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"permissions\": [ { \"resource_server_identifier\": \"API_ID\", \"permission_name\": \"PERMISSION_NAME\" }, { \"resource_server_identifier\": \"API_ID\", \"permission_name\": \"PERMISSION_NAME\" } ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `ROLE_ID` | Τhe ID of the role for which you want to remove permissions. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:roles`. |
+| `API_ID` | ID(s) of the API(s) associated with the permission(s) you would like to remove for the specified role. |
+| `PERMISSION_NAME` | Name(s) of the permission(s) you would like to remove for the specified role. |
\ No newline at end of file
diff --git a/articles/api/management/guides/roles/view-role-permissions.md b/articles/api/management/guides/roles/view-role-permissions.md
new file mode 100644
index 0000000000..86a3aec456
--- /dev/null
+++ b/articles/api/management/guides/roles/view-role-permissions.md
@@ -0,0 +1,37 @@
+---
+Title: View Role Permissions
+description: Learn how to view permissions added to a role using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View Role Permissions
+
+This guide will show you how to view the [permissions](/authorization/concepts/rbac) added to a role using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/roles/view-role-permissions). The added permissions and roles are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `GET` call to the [Get Role Permissions endpoint](/api/management/v2#!/Roles/get_role_permission). Be sure to replace `ROLE_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your role ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/roles/ROLE_ID/permissions",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `ROLE_ID` | Τhe ID of the role for which you want to get permissions. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `read:roles`. |
\ No newline at end of file
diff --git a/articles/api/management/guides/roles/view-role-users.md b/articles/api/management/guides/roles/view-role-users.md
new file mode 100644
index 0000000000..8c68a6c5e4
--- /dev/null
+++ b/articles/api/management/guides/roles/view-role-users.md
@@ -0,0 +1,38 @@
+---
+title: View Role Users
+description: Learn how to view users assigned to a role using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+ - users
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View Role Users
+
+This guide will show you how to view the users assigned to a role using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/roles/view-role-users). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `GET` call to the [Get Role Users endpoint](/api/management/v2#!/Roles/get_role_user). Be sure to replace `ROLE_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your role ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/roles/ROLE_ID/users",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `ROLE_ID` | Τhe ID of the role for which you want to get users. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scopes `read:users` and `read:roles`. |
diff --git a/articles/api/management/guides/rules/create-rules.md b/articles/api/management/guides/rules/create-rules.md
new file mode 100644
index 0000000000..0e102f32c0
--- /dev/null
+++ b/articles/api/management/guides/rules/create-rules.md
@@ -0,0 +1,43 @@
+---
+title: Create Rules
+description: Learn how to create a rule using the Auth0 Management API. You can use rules to customize and extend Auth0's capabilities.
+topics:
+ - mgmt-api
+ - rules
+ - extensibility
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Create Rules
+
+This guide will show you how to create [rules](/rules) using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/rules/create-rules).
+
+1. Make a `POST` call to the [Create Rule endpoint](/api/management/v2#!/Rules/post_rules). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `RULE_NAME`, `RULE_SCRIPT`, `RULE_ORDER`, and `RULE_ENABLED` placeholder values with your Management API Access Token, rule name, rule script, rule order number, and rule enabled value, respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/rules",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"name\": \"RULE_NAME\", \"script\": \"RULE_SCRIPT\" }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:rules`. |
+| `RULE_NAME` | Name of the rule you would like to create. The rule name can only contain alphanumeric characters, spaces, and hyphens; it may not start or end with spaces or hyphens. |
+| `RULE_SCRIPT` | Script that contains the code for the rule. Should match what you would enter if you were [creating a new rule using the Dashboard](/dashboard/guides/rules/create-rules). |
+| `RULE_ORDER` (optional) | Integer that represents the order in which the rule should be executed in relation to other rules. Rules with lower numbers are executed before rules with higher numbers. If no order number is provided, the rule will execute last.
+| `RULE_ENABLED` (optional) | Boolean that represents whether the rules is enabled (`true`) or disabled (`false`). |
\ No newline at end of file
diff --git a/articles/api/management/guides/tenants/configure-session-lifetime-settings.md b/articles/api/management/guides/tenants/configure-session-lifetime-settings.md
new file mode 100644
index 0000000000..2e4421e585
--- /dev/null
+++ b/articles/api/management/guides/tenants/configure-session-lifetime-settings.md
@@ -0,0 +1,42 @@
+---
+title: Configure Session Lifetime Settings
+description: Learn how to configure session lengths and limits for a tenant using the Auth0 Management API.
+topics:
+ - idle-timeout
+ - absolute-timeout
+ - session-lifetime-limits
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - integrate-saas-sso
+ - configure-sso
+ - build-an-app
+---
+# Configure Session Lifetime Settings
+
+This guide will show you how to configure session settings for your tenant using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/tenants/configure-session-lifetime-settings).
+
+1. Make a `PATCH` call to the [Tenant Settings endpoint](/api/management/v2#!/tenants/patch_settings). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `SESSION_LIFETIME`, and `IDLE_SESSION_LIFETIME` placeholder values with your Management API Access Token, session lifetime value, and idle session lifetime value, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/tenants/settings",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"session_lifetime\": SESSION_LIFETIME_VALUE, \"idle_session_lifetime\": IDLE_SESSION_LIFETIME_VALUE }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:tenant_settings`. |
+| `IDLE_SESSION_LIFETIME_VALUE` | Timeframe (in hours) after which a user's session will expire if they haven’t interacted with the Authorization Server. Will be superseded by system limits if over 72 hours (3 days) for Developer or Developer Pro or 2,400 hours (100 days) for enterprise plans. |
+| `SESSION_LIFETIME_VALUE` | Timeframe (in hours) after which a user will be required to log in again, regardless of their activity. Will be superseded by system limits if over 720 hours (30 days) for Developer or Developer Pro or 8,760 hours (365 days) for enterprise plans. |
diff --git a/articles/api/management/guides/users/assign-permissions-users.md b/articles/api/management/guides/users/assign-permissions-users.md
new file mode 100644
index 0000000000..1bca553a35
--- /dev/null
+++ b/articles/api/management/guides/users/assign-permissions-users.md
@@ -0,0 +1,50 @@
+---
+title: Assign Permissions to Users
+description: Learn how to assign permissions to a user using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Assign Permissions to Users
+
+This guide will show you how to assign [permissions](/authorization/concepts/rbac) to a user using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/users/assign-permissions-users). The assigned permissions can be used with the API Authorization Core feature set.
+
+::: note
+Adding permissions directly to a user circumvents the benefits of [role-based access control (RBAC)](/authorization/concepts/rbac) and is not typically recommended.
+:::
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `POST` call to the [Assign User Permissions endpoint](/api/management/v2#!/Users/post_permissions). Be sure to replace `USER_ID`, `MGMT_API_ACCESS_TOKEN`, `API_IDENTIFIER`, and `PERMISSION_NAME` placeholder values with your user ID, Management API Access Token, API Identifier(s), and permission name(s), respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/users/USER_ID/permissions",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"permissions\": [ { \"resource_server_identifier\": \"API_IDENTIFIER\", \"permission_name\": \"PERMISSION_NAME\" }, { \"resource_server_identifier\": \"API_IDENTIFIER\", \"permission_name\": \"PERMISSION_NAME\" } ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `USER_ID` | Τhe ID of the user for whom you want to assign permissions. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:users`. |
+| `API_IDENTIFIER` | Identifier(s) of the API(s) associated with the permission(s) you would like to assign for the specified user. |
+| `PERMISSION_NAME` | Name(s) of the permission(s) you would like to assign for the specified user. |
diff --git a/articles/api/management/guides/users/assign-roles-users.md b/articles/api/management/guides/users/assign-roles-users.md
new file mode 100644
index 0000000000..12b652a0d7
--- /dev/null
+++ b/articles/api/management/guides/users/assign-roles-users.md
@@ -0,0 +1,45 @@
+---
+title: Assign Roles to Users
+description: Learn how to assign roles to a user using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - roles
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Assign Roles to Users
+
+This guide will show you how to assign [roles](/authorization/concepts/rbac) to a user using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/users/assign-roles-users). The assigned roles can be used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `POST` call to the [Assign User Roles endpoint](/api/management/v2#!/Users/post_user_roles). Be sure to replace `USER_ID`, `MGMT_API_ACCESS_TOKEN`, and `ROLE_ID` placeholder values with your user ID, Management API Access Token, and role ID(s), respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/users/USER_ID/roles",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"roles\": [ \"ROLE_ID\", \"ROLE_ID\" ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `USER_ID` | Τhe ID of the user to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scopes `read:roles` and `update:users`. |
+| `ROLE_ID` | ID(s) of the role(s) you would like to add for the specified user. |
\ No newline at end of file
diff --git a/articles/api/management/guides/users/remove-user-permissions.md b/articles/api/management/guides/users/remove-user-permissions.md
new file mode 100644
index 0000000000..1cdf1f4c6d
--- /dev/null
+++ b/articles/api/management/guides/users/remove-user-permissions.md
@@ -0,0 +1,46 @@
+---
+title: Remove Permissions from Users
+description: Learn how to remove permissions directly assigned to a user using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Remove Permissions from Users
+
+This guide will show you how to remove the [permissions](/authorization/concepts/rbac) directly assigned to a user using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/users/remove-user-permissions). The assigned permissions are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `DELETE` call to the [Delete User Permissions endpoint](/api/management/v2#!/Users/delete_permissions). Be sure to replace `USER_ID`, `MGMT_API_ACCESS_TOKEN`, `API_ID`, and `PERMISSION_NAME` placeholder values with your user ID, Management API Access Token, API ID(s), and permission name(s), respectively.
+
+```har
+{
+ "method": "DELETE",
+ "url": "https://${account.namespace}/api/v2/users/USER_ID/permissions",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"permissions\": [ { \"resource_server_identifier\": \"API_ID\", \"permission_name\": \"PERMISSION_NAME\" }, { \"resource_server_identifier\": \"API_ID\", \"permission_name\": \"PERMISSION_NAME\" } ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `USER_ID` | Τhe ID of the user to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:users`. |
+| `API_ID` | ID(s) of the API(s) associated with the permission(s) you would like to remove for the specified user. |
+| `PERMISSION_NAME` | Name(s) of the permission(s) you would like to remove for the specified user. |
\ No newline at end of file
diff --git a/articles/api/management/guides/users/remove-user-roles.md b/articles/api/management/guides/users/remove-user-roles.md
new file mode 100644
index 0000000000..10e60f99fe
--- /dev/null
+++ b/articles/api/management/guides/users/remove-user-roles.md
@@ -0,0 +1,45 @@
+---
+title: Remove Roles from Users
+description: Learn how to remove the roles assigned to a user using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - roles
+ - users
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Remove Roles from Users
+
+This guide will show you how to remove the [roles](/authorization/concepts/rbac) assigned to a user using Auth0's Management API. This task can also be performed using the Dashboard by either [removing users from a role](/dashboard/guides/users/remove-role-users) or [removing roles from a user](/dashboard/guides/users/remove-user-roles). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `DELETE` call to the [Delete User Roles endpoint](/api/management/v2#!/Users/delete_user_roles). Be sure to replace `USER_ID`, `MGMT_API_ACCESS_TOKEN`, and `ROLE_ID` placeholder values with your user ID, Management API Access Token, and role ID(s), respectively.
+
+```har
+{
+ "method": "DELETE",
+ "url": "https://${account.namespace}/api/v2/users/USER_ID/roles",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"roles\": [ \"ROLE_ID\", \"ROLE_ID\" ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `USER_ID` | Τhe ID of the user to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:users`. |
+| `ROLE_ID` | ID(s) of the role(s) you would like to remove for the specified user. |
\ No newline at end of file
diff --git a/articles/api/management/guides/users/set-root-attributes-user-import.md b/articles/api/management/guides/users/set-root-attributes-user-import.md
new file mode 100644
index 0000000000..ac6df80bdd
--- /dev/null
+++ b/articles/api/management/guides/users/set-root-attributes-user-import.md
@@ -0,0 +1,40 @@
+---
+title: Set Root Attributes During User Import
+description: Learn how to set root attributes for users during import using the Auth0 Management API.
+topics:
+ - mgmt-api
+ - root-attributes
+ - users
+ - user-profile
+ - user-import
+contentType:
+ - how-to
+useCase:
+ - manage-users
+---
+# Set Root Attributes During User Import
+
+This guide will show you how to set root attributes for a user during import using Auth0's Management API. This allows you to minimize the number of API calls required to set root attributes when importing users. To see which attributes you can import, visit [Normalized User Profile Structure](/users/references/user-profile-structure).
+
+1. Make a `POST` call to the [Create Job to Import Users endpoint](/api/management/v2#!/Jobs/post_users_imports). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `CONNECTION_ID`, and `JSON_USER_FILE_PATH` placeholder values with your Management API Access Token, connection ID, and users filename, respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/jobs/usersimports",
+ "headers": [
+ { "name": "Content-Type", "value": "multipart/form-data " },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ],
+ "postData": {
+ "mimetype": "multipart/form-data",
+ "text": "{ \"connection_id\": \"CONNECTION_ID\", \"users\": \"JSON_USER_FILE_PATH\" }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:users`. |
+| `CONNECTION_ID` | ID of the connection to which the users will be inserted. You can retrieve this info using the [Get All Connections endpoint](/api/management/v2#!/Connections/get_connections). |
+| `JSON_USER_FILE_PATH` | Filename of the file that contains the users to be imported. File should be in JSON format and include root attributes for users. For a list of available attributes, see [User Profile Attributes](/users/references/user-profile-structure#attributes). For an example of the file format, see [Bulk User Import Database Schema and Examples](/users/references/bulk-import-database-schema-examples). |
\ No newline at end of file
diff --git a/articles/api/management/guides/users/set-root-attributes-user-signup.md b/articles/api/management/guides/users/set-root-attributes-user-signup.md
new file mode 100644
index 0000000000..7eebeb41e9
--- /dev/null
+++ b/articles/api/management/guides/users/set-root-attributes-user-signup.md
@@ -0,0 +1,53 @@
+---
+title: Set Root Attributes During User Sign-Up
+description: Learn how to set root attributes for users during sign-up using the Auth0 Management API.
+topics:
+ - mgmt-api
+ - root-attributes
+ - users
+ - user-profile
+ - user-signup
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - manage-users
+---
+# Set Root Attributes During User Sign-Up
+
+This guide will show you how to set root attributes for a user during sign-up using Auth0's Management API. This allows you to minimize the number of API calls required to set root attributes when creating users.
+
+1. Make a `POST` call to the [Create a User endpoint](/api/management/v2#!/Users/post_users). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `CONNECTION_NAME`, `EMAIL_VALUE`, `PASSWORD_VALUE`, `GIVEN_NAME_VALUE`, `FAMILY_NAME_VALUE`, `NAME_VALUE`, `NICKNAME_VALUE`, and `PICTURE` placeholder values with your Management API Access Token, initial connection name, email address, password, given name, family name, name, nickname, and picture URL, respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/users",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"connection\": CONNECTION_NAME, \"email\": EMAIL_VALUE, \"password\": PASSWORD_VALUE, \"given_name\": GIVEN_NAME_VALUE, \"family_name\": FAMILY_NAME_VALUE,\"name\": NAME_VALUE, \"nickname\": NICKNAME_VALUE,\"picture\": PICTURE_VALUE }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:users`. |
+| `CONNECTION_NAME` | Name of the connection through which the initial user information was received. |
+| `EMAIL_VALUE` | Email address of the user to be created. |
+| `PASSWORD_VALUE` | Password of the user to be created. |
+| `GIVEN_NAME_VALUE` | Given name of the user to be created. |
+| `FAMILY_NAME_VALUE` | Family name of the user to be created. |
+| `NAME_VALUE` | Full name of the user to be created. |
+| `NICKNAME_VALUE` | Nickname of the user to be created. |
+| `PICTURE_VALUE` | URL of the picture for the user to be created. |
+
+::: note
+If you are using Lock or the [public signup endpoint](/api/authentication#signup) for user sign-up, you can set root attributes using the same method.
+:::
diff --git a/articles/api/management/guides/users/update-root-attributes-users.md b/articles/api/management/guides/users/update-root-attributes-users.md
new file mode 100644
index 0000000000..97be3eabfd
--- /dev/null
+++ b/articles/api/management/guides/users/update-root-attributes-users.md
@@ -0,0 +1,52 @@
+---
+title: Update Root Attributes for Users
+description: Learn how to update root attributes in existing user profiles using the Auth0 Management API.
+topics:
+ - mgmt-api
+ - root-attributes
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - manage-users
+---
+# Update Root Attributes for Users
+
+This guide will show you how to update root attributes for an existing user profile using Auth0's Management API.
+
+Auth0's [Normalized User Profile](/users/references/user-profile-structure) features [root attributes](/users/references/user-profile-structure#user-profile-attributes) that you can update. The specific root attributes that you can update depend on the [connection](/identityproviders) type you're using. For details relevant to the connection you are using, see [Updating User Profile Root Attributes](/users/normalized/auth0/update-root-attributes).
+
+1. Make a `PATCH` call to the [Update a User endpoint](/api/management/v2#!/Users/patch_users_by_id). Be sure to replace `USER_ID`, `MGMT_API_ACCESS_TOKEN`, `GIVEN_NAME_VALUE`, `FAMILY_NAME_VALUE`, `NAME_VALUE`, `NICKNAME_VALUE`, and `PICTURE` placeholder values with your user ID, Management API Access Token, given name, family name, name, nickname, and picture URL, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/users/USER_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"given_name\": GIVEN_NAME_VALUE, \"family_name\": FAMILY_NAME_VALUE,\"name\": NAME_VALUE, \"nickname\": NICKNAME_VALUE,\"picture\": PICTURE_VALUE }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `USER_ID` | Τhe ID of the user to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:users`. |
+| `GIVEN_NAME_VALUE` | Given name of the user to be updated. |
+| `FAMILY_NAME_VALUE` | Family name of the user to be updated. |
+| `NAME_VALUE` | Full name of the user to be updated. |
+| `NICKNAME_VALUE` | Nickname of the user to be updated. |
+| `PICTURE_VALUE` | URL of the picture for the user to be updated. |
+
+## Removing attributes
+
+Setting any value to `null` will remove the attribute for the user.
diff --git a/articles/api/management/guides/users/view-user-permissions.md b/articles/api/management/guides/users/view-user-permissions.md
new file mode 100644
index 0000000000..f24b5c02d7
--- /dev/null
+++ b/articles/api/management/guides/users/view-user-permissions.md
@@ -0,0 +1,38 @@
+---
+title: View Permissions Assigned to Users
+description: Learn how to view permissions assigned to a user using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View Permissions Assigned to Users
+
+This guide will show you how to view the [permissions](/authorization/concepts/rbac) assigned to a user using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/users/view-user-permissions). The assigned permissions are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `GET` call to the [Get User Permissions endpoint](/api/management/v2#!/Users/get_permissions). Be sure to replace `USER_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your user ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/users/USER_ID/permissions",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `USER_ID` | Τhe ID of the user for whom you want to get permissions. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `read:users`. |
\ No newline at end of file
diff --git a/articles/api/management/guides/users/view-user-roles.md b/articles/api/management/guides/users/view-user-roles.md
new file mode 100644
index 0000000000..af6fb61d60
--- /dev/null
+++ b/articles/api/management/guides/users/view-user-roles.md
@@ -0,0 +1,39 @@
+---
+title: View Roles Assigned to Users
+description: Learn how to view roles assigned to a user using the Auth0 Management API. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - mgmt-api
+ - permissions
+ - roles
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View Roles Assigned to Users
+
+This guide will show you how to view the [roles](/authorization/concepts/rbac) assigned to a user using Auth0's Management API. This task can also be performed [using the Dashboard](/dashboard/guides/users/view-user-roles). The assigned roles are used with the API Authorization Core feature set.
+
+<%= include('../../../../authorization/_includes/_enable-authz-core') %>
+
+1. Make a `GET` call to the [Get User Roles endpoint](/api/management/v2#!/Users/get_user_roles). Be sure to replace `USER_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your user ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/users/USER_ID/roles",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `USER_ID` | Τhe ID of the user for whom you want to get roles. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scopes `read:users` and `read:roles`. |
\ No newline at end of file
diff --git a/articles/api/management/v1/index.md b/articles/api/management/v1/index.md
index b6c9fb97ab..e0673851e7 100644
--- a/articles/api/management/v1/index.md
+++ b/articles/api/management/v1/index.md
@@ -1,13 +1,17 @@
---
description: An overview of the Auth0 Management API v1 which has been deprecated.
+topics:
+ - apis
+ - management-api
+contentType:
+ - reference
+ - index
+useCase: invoke-api
---
# Management API v1 (deprecated)
-::: warning
-This version of the Management API has been deprecated.
-Please use the [new version](/api/v2) instead.
-:::
+<%= include('../../../_includes/_version_warning_api') %>
## Authentication
@@ -16,19 +20,16 @@ Please use the [new version](/api/v2) instead.
Obtain a token to call the API
-Auth0 API requires an `access_token`. You can get one by authenticating with your `client_id` and `client_secret` (It will be valid for 24 hours). To obtain the global client ID and global client secret see the **Advanced** tab under [Tenant Settings](${manage_url}/#/tenant/advanced) in the Auth0 dashboard.
+Auth0 API requires an Access Token. You can get one by authenticating with your `client_id` and `client_secret` (It will be valid for 24 hours). To obtain the global client ID and global client secret see the **Advanced** tab under [Tenant Settings](${manage_url}/#/tenant/advanced) in the Auth0 dashboard.
```text
POST /oauth/token
-Content-Type: application/json
-{
- "client_id": "",
- "client_secret": "",
- "grant_type": "client_credentials"
-}
+Content-Type: application/x-www-form-urlencoded
+
+grant_type=client_credentials&client_id=${account.clientId}&client_secret=YOUR_CLIENT_SECRET
```
-Once authenticated, the `access_token` can be included in the request as part of the querystring ( `?access_token=...`) or in an HTTP header (`Authorization: Bearer ...access_token...`).
+Once authenticated, the Access Token can be included in the request as part of the query string ( `?access_token=...`) or in an HTTP header (`Authorization: Bearer ...access_token...`).
## Users
@@ -61,25 +62,13 @@ Authorization: Bearer {token}
Gets an user by id
-Gets an user who have logged in through any of your connections that has a given id.
+Gets a user who has logged in through any of your connections that has a given id.
```text
GET /api/users/{user_id}
Authorization: Bearer {token}
```
-
-
GET /api/users/{user_id}/devices
-
Gets all user's devices
-
-
-Gets all devices/refresh_tokens being used by the user.
-
-```text
-GET /api/users/{user_id}/devices
-Authorization: Bearer {token}
-```
-
GET /api/connections/{connection}/users
Gets all users from an enterprise directory
@@ -98,9 +87,9 @@ Authorization: Bearer {token}
**Search** remarks: Depending on the connection's type the search will be done in different fields:
-* Active Directory/LDAP: by default uses Ambigous name resolution ([ANR](http://technet.microsoft.com/en-us/library/cc755809(v=ws.10).aspx)) which expands to givenName (first name), sn (surname, or last name), displayName, RDN, legacyExchangeDN, physicalDeliveryOfficeName (for example, Building A, Suite 1234), proxyAddresses (the collection of e-mail addresses over all e-mail address spaces that the Exchange server knows about).
+* Active Directory/LDAP: by default uses ambiguous name resolution ([ANR](http://technet.microsoft.com/en-us/library/cc755809(v=ws.10).aspx)) which expands to givenName (first name), sn (surname, or last name), displayName, RDN, legacyExchangeDN, physicalDeliveryOfficeName (for example, Building A, Suite 1234), proxyAddresses (the collection of email addresses over all email address spaces that the Exchange server knows about).
* Database Connections (not custom): Name/Email case insensitive.
-* Google Apps: Email/username case insensitive.
+* G Suite: Email/username case insensitive.
* WAAD/WAAD2: Name/Email case insensitive.
* Windows Azure Active Directory or Office365: name/email case insensitive
Heads up! If the connection does not support querying for users (for instance ADFS, SAMLP), it will return the users who have logged in through that connection.
@@ -117,9 +106,9 @@ Authorization: Bearer {token}
Search users from all enterprise directories based on the specified `criteria`. The parameter is mandatory.
**Search** remarks: Depending on the connection's type the search will be done in different fields:
-* Active Directory/LDAP: by default uses Ambigous name resolution ([ANR](http://technet.microsoft.com/en-us/library/cc755809(v=ws.10).aspx)) which expands to givenName (first name), sn (surname, or last name), displayName, RDN, legacyExchangeDN, physicalDeliveryOfficeName (for example, Building A, Suite 1234), proxyAddresses (the collection of e-mail addresses over all e-mail address spaces that the Exchange server knows about).
+* Active Directory/LDAP: by default uses ambiguous name resolution ([ANR](http://technet.microsoft.com/en-us/library/cc755809(v=ws.10).aspx)) which expands to givenName (first name), sn (surname, or last name), displayName, RDN, legacyExchangeDN, physicalDeliveryOfficeName (for example, Building A, Suite 1234), proxyAddresses (the collection of email addresses over all email address spaces that the Exchange server knows about).
* Database Connections (not custom): Name/Email case insensitive.
-* Google Apps: Email/username case insensitive.
+* G Suite: Email/username case insensitive.
* WAAD/WAAD2: Name/Email case insensitive.
* Windows Azure Active Directory or Office365: name/email case insensitive
Heads up! If the connection does not support querying for users (for instance ADFS, SAMLP), it will return the users who have logged in through that connection.
@@ -341,7 +330,7 @@ Authorization: Bearer {token}
Revokes a Refresh Token
-Revokes a user's Refresh Token
+Revokes a user's Refresh Token
```text
DELETE /api/users/{user_id}/refresh_tokens/{refresh_token}
@@ -412,7 +401,7 @@ Authorization: Bearer {token}
Content-Type: application/json
{
"name": ""
- "strategy": "waad|google-apps|adfs|PingFederate|samlp|auth0",
+ "strategy": "waad|g-suite|adfs|PingFederate|samlp|auth0",
"options": {
"tenant_domain":
"domain_aliases":
@@ -439,7 +428,7 @@ Content-Type: application/json
Updates a connection. The body of the request must include the `options` object with the connection parameters and the `status`.
-The request's body depends on the strategy that was used to create the connection. Select a strategy: waad google-apps adfs PingFederate samlp auth0
+The request's body depends on the strategy that was used to create the connection. Select a strategy: waad g-suite adfs PingFederate samlp auth0
```text
PUT /api/connections/{connection-name}
@@ -481,7 +470,7 @@ Authorization: Bearer {token}
Creates a new applications/APIs
-Create an application. The body of the request can include the `name` and `callbacks` parameters.
+Create an application. The body of the request can include the `name` and `callbacks` parameters.
```text
POST /api/clients
@@ -696,13 +685,13 @@ The following is a description of the values returned by the request:
* `total`: The amount of entries in the page.
* `limit`: The maximum amount of items in a page.
* `logs`: A collection of log entries.
- * `date`: The moment when the event occured.
+ * `date`: The moment when the event occurred.
* `connection`: The connection related to the event.
* `client_id`: The id of the application related to the event.
* `client_name`: The name of the application related to the event.
* `ip`: The IP address from where the request that caused the log entry originated.
- * `user_id`: The user id releated to the event.
- * `user_name`: The user name releated to the event.
+ * `user_id`: The user id related to the event.
+ * `user_name`: The user name related to the event.
* `description`: The event's description.
* `user_agent`: The user agent that was used to cause the creation of the log entry.
* `type`: An abbreviation of the event type. Refer to the event acronym mappings below for the mapping between abbreviations and their meaning.
@@ -743,10 +732,10 @@ Retrieves data about log entries based on the specified parameters. Log entries
* `fields`: Can be used to either include or exclude the specified fields by providing a comma (,) separated list of fields, for example `at,c,cn,un`. If no list is provided all fields are included in the response.
* `exclude_fields`: To exclude the fields `exclude_fields=true` must be used (if not specified it defaults to false).
Possible values for `field` are:
-* `date`: The moment when the event occured.
+* `date`: The moment when the event occurred.
* `connection`: The connection related to the event.
* `client_name`: The name of the application related to the event.
-* `user_name`: The user name releated to the event.
+* `user_name`: The user name related to the event.
```text
GET /api/logs?page={number}&per_page={items}&sort={field}:{-1|1}&fields={fields}&exclude_fields{true|false}
@@ -760,13 +749,13 @@ The following is a description of the values returned by the request:
* `total`: The amount of entries in the page.
* `limit`: The maximum amount of items in a page.
* `logs`: A collection of log entries.
- * `date`: The moment when the event occured.
+ * `date`: The moment when the event occurred.
* `connection`: The connection related to the event.
* `client_id`: The id of the application related to the event.
* `client_name`: The name of the application related to the event.
* `ip`: The IP address from where the request that caused the log entry originated.
- * `user_id`: The user id releated to the event.
- * `user_name`: The user name releated to the event.
+ * `user_id`: The user id related to the event.
+ * `user_name`: The user name related to the event.
* `description`: The event's description.
* `user_agent`: The user agent that was used to cause the creation of the log entry.
* `type`: An abbreviation of the event type. Refer to the event acronym mappings below for the mapping between abbreviations and their meaning.
@@ -807,7 +796,7 @@ If no fields are provided a case insensitive 'starts with' search is performed o
* `user_name`
Otherwise, you can specify multiple fields and specify the search using the `%field%:%search%`, for example: `application:node user:"John@contoso.com"`.
-Values specified without quotes are matched using a case insensitive 'starts with' search. If quotes are used a case insensitve exact search is used. If multiple fields are used, the AND operator is used to join the clauses.
+Values specified without quotes are matched using a case insensitive 'starts with' search. If quotes are used a case insensitive exact search is used. If multiple fields are used, the AND operator is used to join the clauses.
##### Available Fields
* `application`: Maps to the `client_name` field.
@@ -826,13 +815,13 @@ The following is a description of the values returned by the request:
* `total`: The amount of entries in the page.
* `limit`: The maximum amount of items in a page.
* `logs`: A collection of log entries.
- * `date`: The moment when the event occured.
+ * `date`: The moment when the event occurred.
* `connection`: The connection related to the event.
* `client_id`: The id of the application related to the event.
* `client_name`: The name of the application related to the event.
* `ip`: The IP address from where the request that caused the log entry originated.
- * `user_id`: The user id releated to the event.
- * `user_name`: The user name releated to the event.
+ * `user_id`: The user id related to the event.
+ * `user_name`: The user name related to the event.
* `description`: The event's description.
* `user_agent`: The user agent that was used to cause the creation of the log entry.
* `type`: An abbreviation of the event type. Refer to the event acronym mappings below for the mapping between abbreviations and their meaning.
@@ -883,13 +872,13 @@ The following is a description of the values returned by the request:
* `total`: The amount of entries in the page.
* `limit`: The maximum amount of items in a page.
* `logs`: A collection of log entries.
- * `date`: The moment when the event occured.
+ * `date`: The moment when the event occurred.
* `connection`: The connection related to the event.
* `client_id`: The id of the application related to the event.
* `client_name`: The name of the application related to the event.
* `ip`: The IP address from where the request that caused the log entry originated.
- * `user_id`: The user id releated to the event.
- * `user_name`: The user name releated to the event.
+ * `user_id`: The user id related to the event.
+ * `user_name`: The user name related to the event.
* `description`: The event's description.
* `user_agent`: The user agent that was used to cause the creation of the log entry.
* `type`: An abbreviation of the event type. Refer to the event acronym mappings below for the mapping between abbreviations and their meaning.
diff --git a/articles/api/management/v1/reference.md b/articles/api/management/v1/reference.md
index e8ff38b2a7..3d0af562df 100644
--- a/articles/api/management/v1/reference.md
+++ b/articles/api/management/v1/reference.md
@@ -2,10 +2,17 @@
description: Management API V1 reference page.
section: apis
toc: true
+topics:
+ - apis
+ - management-api
+contentType: reference
+useCase: invoke-api
---
# Auth0 Management API Reference
+<%= include('../../../_includes/_version_warning_api') %>
+
### API endpoint
```text
@@ -13,7 +20,7 @@ https://${account.namespace}/api
```
### Authentication
-Each API request must include an Access Token, either inside the query string:
+Each API request must include an Access Token, either inside the query string:
```text
https://${account.namespace}/api/connections/?access_token={ACCESS-TOKEN}
@@ -50,7 +57,7 @@ curl https://${account.namespace}/oauth/token --data "client_id=${account.client
```
### Headers
-The `Authorization` header is the only accepted header and is used in place of the query string to send the access_token. All content is returned in JSON. The `Accept` header is ignored for now.
+The `Authorization` header is the only accepted header and is used in place of the query string to send the Access Token. All content is returned in JSON. The `Accept` header is ignored for now.
```text
Authorization: bearer {ACCESS-TOKEN}
@@ -105,12 +112,12 @@ The body of the response is a `connection` object formatted as follows:
| Strategy | For Customers Using |
|:---------|:--------------------|
| `adfs` | On Premises Active Directory or any WS-Federation server |
-| `google-apps` | Google Apps |
+| `g-suite` | G Suite |
| `google-oauth2` |Google (through the OAuth2 protocol) |
| `office365` | Office 365 and Microsoft Azure Active Directory |
| `windowslive` | Microsoft Account (formerly LiveID) |
-When implementing the `office365`, `google-apps` or `adfs` strategies, the following properties are added to the connection object:
+When implementing the `office365`, `g-suite` or `adfs` strategies, the following properties are added to the connection object:
```text
provisioning_ticket: TICKET
@@ -162,7 +169,7 @@ The `options` object returned in the `connection` will be different for each str
| `adfs_server` | (for example: `the-adfs-server.domain.com/FederationMetadata/2007-06/FederationMetadata.xml`). |
| `signInEndpoint`| The URL of the ADFS server where Auth0 will redirect users for login. (for example: `the-adfs-server.company.com/adfs/ls`). |
-###### Google Apps Strategy
+###### G Suite Strategy
```text
{
@@ -181,7 +188,7 @@ The `options` object returned in the `connection` will be different for each str
}
```
-To obtain the `client_id` and `client_secret` for Google Apps connections, see [Google connections](/connections/social/google).
+To obtain the `client_id` and `client_secret` for G Suite connections, see [Google connections](/connections/social/google).
###### Google OAuth2 Strategy
@@ -310,7 +317,7 @@ POST https://${account.namespace}/connections
Content-Type: application/json
```
-The body of the request is formatted as a `connection` object. For example, the following will create a new connection to Google Apps, initially inactive (`status=0`):
+The body of the request is formatted as a `connection` object. For example, the following will create a new connection to G Suite, initially inactive (`status=0`):
```text
{
@@ -323,7 +330,7 @@ The body of the request is formatted as a `connection` object. For example, the
"tenant_domain": GOOG-APP-DOMAIN,
"ext_groups":true //Optional
},
- "strategy": "google-apps"
+ "strategy": "g-suite"
};
```
@@ -339,7 +346,7 @@ For updates, use the PUT method. A PUT works on a specific `connection`, therefo
| Verb | URL | Description |
|:-----|:----|:------------|
|`GET` |https://${account.namespace}/api/users |Gets all users who have logged in through any of your connections. |
-|`GET` |https://${account.namespace}/api/connections/{connection}/users|Gets all users from an enterprise directory like Office365 / Microsoft Azure Active Directory or a Google Apps domain.|
+|`GET` |https://${account.namespace}/api/connections/{connection}/users|Gets all users from an enterprise directory like Office365 / Microsoft Azure Active Directory or a G Suite domain.|
|`GET` |https://${account.namespace}/api/socialconnections/users |Gets all users who have logged in through any of the enabled social connections. |
::: note
@@ -372,7 +379,7 @@ Most attributes in the `user` object are self-explanatory. Some comments are bel
|`issuer` | The name of the authentication server. In the example above it is the URL of Fabrikam's ADFS server used.|
|`user_id` | (for example: _the-adfs-server.domain.com/FederationMetadata/2007-06/FederationMetadata.xml_). |
|`picture` | The URL of the user's gravatar, if available. |
-|`user_id` | A "friendly" unique identifier composed of the strategy plus a unique identifier from the `issuer` (for example: e-mail, and so on). |
+|`user_id` | A "friendly" unique identifier composed of the strategy plus a unique identifier from the `issuer` (for example: email, and so on). |
#### Other resources
diff --git a/articles/api/management/v1/use-cases.md b/articles/api/management/v1/use-cases.md
deleted file mode 100644
index 89d3f1d663..0000000000
--- a/articles/api/management/v1/use-cases.md
+++ /dev/null
@@ -1,73 +0,0 @@
----
-description: This page lists the API features that are only available in Management API v1.
-section: apis
----
-
-# Management API v1 Use Cases
-
-Currently, there are API features and functionality that are only available in the [Management API v1](/api/v1). If your business process or configuration requires these features, please continue to use the API v1.
-
-The features only available in Management API v1 include:
-
-* [Active Directory Connector Monitoring](#active-directory-connector-monitoring)
-* [Application Users](#application-users)
-* [Email](#email)
-* [Enterprise Users/Directory Searching](#enterprise-users/directory-searching)
-* [Impersonation](#impersonation)
-* [Rules Configuration](#rules-configuration)
-* [Searching via the PSaaS Appliance](#searching-via-the-auth0-appliance)
-
-## Active Directory Connector Monitoring
-
-In Management API v1, there is a `GET` endpoint that allows you to monitor the status of your Active Directory Connector:
-
-GET `/api/connections/{AUTH0_CONNECTION}/socket`
-
-## Application Users
-
-With Management API v1, after authenticating with the `client_id` and `client_secret` of an application, you can make a `GET` call to the appropriate Users endpoint to return only those users that belong to any specified application connection that is enabled for that application.
-
-[`/api/clients/{client-id}/users`](/api/v1#!#get--api-clients--client-id--users)
-
-## Email
-
-With Management API v1, you can use the `PATCH` email endpoint to update email templates as part of your automation process.
-
-[`/api/emails/{email-template-name}`](/api/v1#put--api-emails--email-template-name-)
-
-## Enterprise Users/Directory Searching
-
-Management API v1 allows you to search directly for users authenticated using enterprise connections, such as Active Directory or Azure Active Directory.
-
-* All users from a specific directory:
-[`/api/connections/{connection}/users`](/api/v1#get--api-connections--connection--users)
-
-* Specific users from a given directory:
-[`/api/connections/{connection}/users?search={criteria}`](/api/v1#get--api-connections--connection--users-search--criteria-)
-
-* All users from all enterprise directories:
-GET `/api/enterpriseconnections/users?search={criteria}`
-
-## Impersonation
-
-Management API v1 includes an impersonation endpoint that generates a link that can be used only once to log in as a specific user for troubleshooting purposes.
-
-[`/users/{user_id}/impersonate`](/auth-api#impersonation)
-
-
-## Rules Configuration
-
-Management API v1 allows you to add values to a global `configuration` object that is accessible to **all** Rules.
-
-* To return all key/value pairs on the global `configuration` object: `GET /api/rules-configs`
-* To create or update a global `configuration` object: `POST /api/rules-configs`
-
-## Searching via the PSaaS Appliance
-
-In Management API v1, you can perform a "starts with" search for users by name or email:
-
-[`/api/users?search={criteria}`](/api/v1#!#get--api-users-search--criteria-).
-
-This functionality works for both cloud instances and the PSaaS Appliance.
-
-In Management API v2, the search operates with reduced functionality and does not currently support the Lucene query syntax.
diff --git a/articles/api/management/v2/changes.md b/articles/api/management/v2/changes.md
index 67e81d297a..b81792b5c1 100644
--- a/articles/api/management/v2/changes.md
+++ b/articles/api/management/v2/changes.md
@@ -3,6 +3,11 @@ description: Describes the major differences between Auth0's Management API v1 a
section: apis
crews: crew-2
toc: true
+topics:
+ - management-api
+ - apis
+contentType: reference
+useCase: invoke-api
---
# Management API v1 vs v2
@@ -11,7 +16,6 @@ This document describes the major differences between Auth0's Management API v1
## tl;dr
* v2 uses JWTs instead of opaque tokens.
-* v2 allows you to send an `id_token` to perform operations on the user to which the `id_token` refers.
* v2 includes `user_metadata` for trivial data about users and `app_metadata` for data that affects how your application functions. Unlike `metadata` in API v1, these fields are not merged into the root `user` object.
* Fewer endpoints on existing features make development easier.
* All endpoints work with ids. Strings (such as `connection_name`) are no longer used.
@@ -25,15 +29,14 @@ This document describes the major differences between Auth0's Management API v1
| v1 Endpoint | Change | v2 Endpoint |
| ----------- | ------ | ----------- |
| [GET /api/users](/api/v1#!#get--api-users) | None. | [GET /api/v2/users](/api/v2#!/Users/get_users) |
-| [GET /api/users?search={criteria}](/api/v1#!#get--api-users-search--criteria-) | Changed parameter and syntax. | Implemented using Elastic Search. See the [get_users](/api/v2#!/Users/get_users) documentation. |
+| [GET /api/users?search={criteria}](/api/v1#!#get--api-users-search--criteria-) | Changed parameter and syntax. | See the [get_users](/api/v2#!/Users/get_users) documentation. |
| [GET /api/users/{user\_id}](/api/v1#!#get--api-users--user_id-) | None. | [GET /api/v2/users/{id}](/api/v2#!/Users/get_users_by_id) also accepts `v2\_id` |
-| [GET /api/connections/{connection}/users](/api/v1#!#get--api-connections--connection--users) | Not available. | TBD. |
-| [GET /api/connections/{connection}/users?search={criteria}](/api/v1#!#get--api-connections--connection--users-search--criteria-) | Not available. | TBD. |
-| [GET /api/enterpriseconnections/users?search={criteria}](/api/v1#!#get--api-enterpriseconnections-users-search--criteria-) | Changed to use search. | Available using `q=identities.isSocial:false AND NOT identities.provider:'auth0'` and `search_engine=v2` in the query string. Other conditions may be added to the search. See the [get_users](/api/v2#!/Users/get_users) documentation. |
-| [GET /api/socialconnections/users?search={criteria}](/api/v1#!#get--api-socialconnections-users-search--criteria-) | Changed to use search. | Available using `q=identities.isSocial:true` and `search_engine=v2` in the query string. Other conditions may be added to the search. See the [get_users](/api/v2#!/Users/get_users) documentation. |
-| [GET /api/clients/{client-id}/users](/api/v1#!#get--api-socialconnections-users-search--criteria-) | Not available. | Not available. |
+| [GET /api/connections/{connection}/users](/api/v1#!#get--api-connections--connection--users) | Changed to use search. | Available using `q=identities.connection:"{connection}"` and `search_engine=v3` in the query string. Other conditions may be added to the search. See the [get_users](/api/v2#!/Users/get_users) documentation. |
+| [GET /api/connections/{connection}/users?search={criteria}](/api/v1#!#get--api-connections--connection--users-search--criteria-) | Changed to use search. | Available using `q=identities.connection:"{connection}"` and `search_engine=v3` in the query string. Other conditions and criteria may be added to the search. See the [get_users](/api/v2#!/Users/get_users) documentation. **For enterprise connections**, only supports searching users that have previously logged in; **external user search is no longer supported.** |
+| [GET /api/enterpriseconnections/users?search={criteria}](/api/v1#!#get--api-enterpriseconnections-users-search--criteria-) | Changed to use search. | Available using `q=identities.isSocial:false AND NOT identities.provider:auth0` and `search_engine=v3` in the query string. Other conditions may be added to the search. See the [get_users](/api/v2#!/Users/get_users) documentation. Only supports searching users that have previously logged in; **external user search is no longer supported.** |
+| [GET /api/socialconnections/users?search={criteria}](/api/v1#!#get--api-socialconnections-users-search--criteria-) | Changed to use search. | Available using `q=identities.isSocial:true` and `search_engine=v3` in the query string. Other conditions may be added to the search. See the [get_users](/api/v2#!/Users/get_users) documentation. |
+| [GET /api/clients/{client-id}/users](/api/v1#!#get--api-socialconnections-users-search--criteria-) | Removed. | Removed. |
| [POST /api/users](/api/v1#!#post--api-users) | None. | [POST /api/v2/users](/api/v2#!/Users/post_users) |
-| [POST /api/users/{user\_id}/send\_verification\_email](/api/v1#!#post--api-users--user_id--send_verification_email) | Not available. | TBD. |
| [POST /api/users/{user\_id}/change\_password\_ticket](/api/v1#!#post--api-users--user_id--change_password_ticket) | None. | [POST /api/v2/tickets/password-change](/api/v2#!/tickets/post_password_change) |
| [POST /api/users/{user\_id}/verification\_ticket](/api/v1#!#post--api-users--user_id--verification_ticket) | None. | [POST /api/v2/tickets/email-verification](/api/v2#!/tickets/post_email_verification) |
| [POST /api/users/{user\_id}/publickey](/api/v1#!#post--api-users--user_id--publickey) | Keys are created per device, not per user. | [POST /api/v2/device-credentials](/api/v2#!/Device_Credentials/post_device_credentials) |
@@ -55,7 +58,7 @@ This document describes the major differences between Auth0's Management API v1
| ----------- | ------ | ----------- |
| [GET /api/clients](/api/v1#!#get--api-clients) | None. | [GET /api/v2/clients](/api/v2#!/Clients/get_clients) |
| [POST /api/clients](/api/v1#!#post--api-clients) | None. | [POST /api/v2/clients](/api/v2#!/Clients/post_clients) |
-| [PUT /api/clients/{client-id}](/api/v1#!#put--api-clients--client-id-) | Not available. | [PUT /api/v2/clients/{id}](/api/v2#!/Clients/patch_clients_by_id) |
+| [PUT /api/clients/{client-id}](/api/v1#!#put--api-clients--client-id-) | Removed. | [PUT /api/v2/clients/{id}](/api/v2#!/Clients/patch_clients_by_id) |
| [PATCH /api/clients/{client-id}](/api/v1#!#patch--api-clients--client-id-) | None. | [PATCH /api/v2/clients/{id}](/api/v2#!/Clients/patch_clients_by_id) |
| [DELETE /api/clients/{client-id}](/api/v1#!#delete--api-clients--client-id-) | None. | [DELETE /api/v2/clients/{id}](/api/v2#!/Clients/delete_clients_by_id) |
@@ -64,15 +67,15 @@ This document describes the major differences between Auth0's Management API v1
| v1 Endpoint | Change | v2 Endpoint |
| ----------- | ------ | ----------- |
| [GET /api/connections](/api/v1#!#get--api-connections) | None. | [GET /api/v2/connections](/api/v2#!/Connections/get_connections) |
-| [GET /api/connections/{connection-name}](/api/v1#!#get--api-connections--connection-name-) | Changed `connection-name` to `id`. | [GET /api/connections/{id}](/api/v2#!/Connections/get_connections_by_id) |
+| [GET /api/connections/{connection-name}](/api/v1#!#get--api-connections--connection-name-) | Use `id` instead of `connection-name`. | [GET /api/connections/{id}](/api/v2#!/Connections/get_connections_by_id) |
| [POST /api/connections](/api/v1#!#post--api-connections) | Added `enabled_clients` property. | [POST /api/v2/connections](/api/v2#!/Connections/post_connections) |
-| [PUT /api/connections/{connection-name}](/api/v1#!#put--api-connections--connection-name-) | Not available. Changed `connection-name` to `id`. | [PATCH /api/v2/connections/{id}](/api/v2#!/Connections/patch_connections_by_id) |
-| [DELETE /api/connections/{connection-name}](/api/v1#!#delete--api-connections--connection-name-) | Changed `connection-name` to `id`. | [DELETE /api/v2/clients/{id}](/api/v2#!/Connections/delete_connections_by_id) |
-| [GET /api/connections/{connection}/users](/api/v1) | None. | [GET /api/v2/users](/api/v2#!/Users/get_users) (see note) |
-| [GET /api/connections/{connection}/users?search={criteria}](/api/v1) | None. | [GET /api/v2/users](/api/v2#!/Users/get_users) (see note) |
+| [PUT /api/connections/{connection-name}](/api/v1#!#put--api-connections--connection-name-) | Removed; use `id` instead of `connection-name`. | [PATCH /api/v2/connections/{id}](/api/v2#!/Connections/patch_connections_by_id) |
+| [DELETE /api/connections/{connection-name}](/api/v1#!#delete--api-connections--connection-name-) | Use `id` instead of `connection-name`. | [DELETE /api/v2/clients/{id}](/api/v2#!/Connections/delete_connections_by_id) |
+| [GET /api/connections/{connection}/users](/api/v1) | None. | [GET /api/v2/users](/api/v2#!/Users/get_users) (see note) |
+| [GET /api/connections/{connection}/socket](/api/v1) | None. | [GET /api/v2/connections/{id}/status](/api/v2#!/Connections/get_status) |
::: note
-For PSaaS Appliance (search_engine:v1), use `connection` field; for cloud (search_engine:v2), use `q=identities.connection:"connection_name"`
+For Private Cloud (search_engine:v2), use `q=identities.connection:"connection_name"`
:::
### Rules endpoints
@@ -81,20 +84,35 @@ For PSaaS Appliance (search_engine:v1), use `connection` field; for cloud (searc
| ----------- | ------ | ----------- |
| [GET /api/rules](/api/v1#!#get--api-rules-) | None. | [GET /api/v2/rules](/api/v2#!/Rules/get_rules) |
| [POST /api/rules](/api/v1#!#post--api-rules) | None. | [POST /api/v2/rules](/api/v2#!/Rules/post_rules-) |
-| [PUT /api/rules/{rule-name}](/api/v1#!#put--api-rules--rule-name-) | Uses `{id}` instead of `rule-name`. | [PATCH /api/v2/rules/{id}](/api/v2#!/Rules/patch_rules_by_id) |
-| [DELETE /api/rules/{rule-name}](/api/v1#!#delete--api-rules--rule-name-) | Uses `{id}` instead of `rule-name`. | [DELETE /api/v2/rules/{id}](/api/v2#!/Rules/delete_rules_by_id) |
+| [PUT /api/rules/{rule-name}](/api/v1#!#put--api-rules--rule-name-) | Removed; use `id` instead of `rule-name`. | [PATCH /api/v2/rules/{id}](/api/v2#!/Rules/patch_rules_by_id) |
+| [DELETE /api/rules/{rule-name}](/api/v1#!#delete--api-rules--rule-name-) | Use `id` instead of `rule-name`. | [DELETE /api/v2/rules/{id}](/api/v2#!/Rules/delete_rules_by_id) |
+| [GET /api/rules-configs](/api/v1) | None. | [GET /api/v2/rules-configs](/api/v2#!/Rules_Configs/get_rules_configs) |
+| [POST /api/rules-configs](/api/v1) | Removed; perform one call per variable to update. | [PUT /api/v2/rules-configs/{key}](/api/v2#!/Rules_Configs/put_rules_configs_by_key) |
### Logs endpoints
-Logs endpoints have not been implemented in Management API v2. Logs must first be indexed in Elastic Search.
+Logs endpoints in Management API v2 are described at [Search Log Events](https://auth0.com/docs/api/management/v2#!/Logs/get_logs)
+
+| v1 Endpoint | Change | v2 Endpoint |
+| ----------- | ------ | ----------- |
+| [GET /logs](/api/v1#logs) | Syntax Changes, described at [Breaking Changes](https://auth0.com/docs/logs/query-syntax#search-engine-v3-breaking-changes) | [GET /api/v2/logs](/api/v2#!/Logs/get_logs) |
+| [GET /logs/{id}](/api/v1#logs) | None. | [GET /api/v2/logs/{id}](/api/v2#!/Logs/get_logs_by_id) |
+
+### Email Templates endpoints
+
+| v1 Endpoint | Change | v2 Endpoint |
+| ----------- | ------ | ----------- |
+| [GET /api/emails/{email-template-name}](/api/v1#email-templates) | `disabled` renamed to `enabled`. | [GET /api/v2/email-templates/{templateName}](/api/v2#!/Email_Templates/get_email_templates_by_templateName) |
+| [POST /api/emails](/api/v1#email-templates) | `disabled` renamed to `enabled`. | [POST /api/v2/email-templates](https://auth0.com/docs/api/management/v2#!/Email_Templates/post_email_templates) |
+| [PUT /api/emails/{email-template-name}](/api/v1#email-templates) | `disabled` renamed to `enabled`. | [PUT /api/v2/email-templates/{templateName}](https://auth0.com/docs/api/management/v2#!/Email_Templates/put_email_templates_by_templateName) |
## Authentication mechanism
-Auth0's API v1 requires sending an `access_token` obtained by performing a [`POST /oauth/token`](/api/v1#!#post--oauth-token) request along with the `clientId` and `clientSecret`. All subsequent requests must include the `access_token` in the `Authorization` header: `Authorization: Bearer {access_token}`.
+Auth0's API v1 requires sending an Access Token obtained by performing a [`POST /oauth/token`](/api/v1#!#post--oauth-token) request along with the `clientId` and `clientSecret`. All subsequent requests must include the Access Token in the `Authorization` header: `Authorization: Bearer {access_token}`.
-Auth0's API v2 requires sending an Access Token with specific scope(s). To perform requests with API v2, use the `Authorization` header: `Authorization: Bearer YOUR_ACCESS_TOKEN`.
+Auth0's API v2 requires sending an Access Token with specific scope(s). To perform requests with API v2, use the `Authorization` header: `Authorization: Bearer YOUR_ACCESS_TOKEN`.
-To use an endpoint, at least one of its available scopes (as listed in [Management API v2 explorer](/api/v2)) must be specified for the JWT. The actions available on an endpoint depend on the JWT scope. For example, if a JWT has the `update:users_app_metadata` scope, the [PATCH users `app_metadata`](/api/v2#!/users/patch_users_by_id) action is available, but not other properties.
+To use an endpoint, at least one of its available scopes (as listed in [Management API v2 explorer](/api/v2)) must be specified for the JWT. The actions available on an endpoint depend on the JWT scope. For example, if a JWT has the `update:users_app_metadata` scope, the [PATCH users `app_metadata`](/api/v2#!/Users/patch_users_by_id) action is available, but not other properties.
There is a subset of scopes that your application can use in order to perform a subset of operations on behalf of the currently logged-in user. These are:
@@ -110,7 +128,7 @@ So, for example, if the Access Token contains the scope `update:current_user_met
## User metadata
-In the Management API v1, [`user.metadata`](/api/v1#!#patch--api-users--user_id--metadata) provides additional information about a user which is not part of the default user claims. When working with rules and other API endpoints, `metadata` is merged into the root user. For example, if the following data is stored for a user with `email` "jane.doe@gmail.com":
+In the Management API v1, [`user.metadata`](/api/v1#!#patch--api-users--user_id--metadata) provides additional user information that is not part of the default user claims. When working with rules and other API endpoints, `metadata` is merged into the root user. For example, if the following data is stored for a user with `email` "jane.doe@gmail.com":
```javascript
{
@@ -120,7 +138,7 @@ In the Management API v1, [`user.metadata`](/api/v1#!#patch--api-users--user_id-
}
```
-when working with rules or retrieving the user from the API you would get:
+when working with rules or retrieving the user from the API, you would get:
```javascript
console.log(user.email); // "jane.doe@gmail.com"
@@ -199,7 +217,7 @@ In Management API v1, different endpoints are used to update the various user pr
* [`PUT /api/users/{user_id}/metadata`](/api/v1#!#put--api-users--user_id--metadata)
* [`PUT /api/users/{user_id}/password`](/api/v1#!#put--api-users--user_id--password)
-In API v2, these are simplified into the single endpoint [`PATCH /api/v2/users/{id}`](/api/v2#!/users/patch_users_by_id) which allows you to modify these (and other) user properties.
+In API v2, these are simplified into the single endpoint [`PATCH /api/v2/users/{id}`](/api/v2#!/Users/patch_users_by_id) which allows you to modify these (and other) user properties.
### All endpoints require ids
diff --git a/articles/api/management/v2/create-m2m-app.md b/articles/api/management/v2/create-m2m-app.md
new file mode 100644
index 0000000000..ef3cf0d79c
--- /dev/null
+++ b/articles/api/management/v2/create-m2m-app.md
@@ -0,0 +1,44 @@
+---
+description: How to create and authorize a machine-to-machine application for calling Management API endpoints using Access Tokens.
+section: apis
+toc: true
+topics:
+ - apis
+ - management-api
+ - tokens
+contentType:
+ - how-to
+useCase: invoke-api
+---
+
+# Create and Authorize a Machine-to-Machine Application
+
+The first time you get a token for the Management API is when you complete the configuration in the Auth0 [Dashboard](${manage_url}). You won't have to do this again unless you create a new tenant. We recommend that you create a token exclusively for authorizing access to the Management API instead of reusing another one you might have.
+
+To create and authorize a Machine-to-Machine Application for the Management API:
+
+1. Go to [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer)
+2. Click the button __Create & Authorize a Test Application__. A new application has been created and it's authorized to access the Management API.
+
+
+
+The application created in the steps above has been granted __all__ the Management API scopes. This means that it can access all endpoints.
+
+::: panel How can I find out which scopes/permissions are required?
+Each machine-to-machine application that accesses an API must be granted a set of scopes. Scopes are permissions that should be granted by the owner. Each [Auth0 Management API v2](/api/management/v2) endpoint requires specific scopes. To see the required scopes/permissions for each endpoint, go to the [Management API Explorer](/api/management/v2#!) and find the endpoint you want to call. Each endpoint has a section called **Scopes** listing all the scopes that the endpoint requires. For example, the [Get all clients](/api/management/v2#!/Clients/get_clients) endpoint requires the scopes `read:clients` and `read:client_keys`.
+:::
+
+## Example: Get All Clients Endpoint
+
+The [Get all clients](/api/management/v2#!/Clients/get_clients) endpoint requires the scopes `read:clients` and `read:client_keys`, while the [Create an application](/api/management/v2#!/Clients/post_clients) endpoint requires the scope `create:clients`. From that we can deduce that if we need to read _and_ create applications, then our token should include three scopes: `read:clients`, `read:client_keys` and `create:clients`.
+
+If you have multiple applications that should access the Management API, and you need different sets of scopes per app, we recommend creating a new machine-to-machine application for each one. For example, if one application is to read and create users (`create:users`, `read:users`) and another to read and create applications (`create:clients`, `read:clients`) create two applications (one for user scopes, one for applications) instead of one.
+
+## Keep reading
+
+* [Get Access Tokens for Testing](/api/management/v2/get-access-tokens-for-test)
+* [Get Access Tokens for Production](/api/management/v2/get-access-tokens-for-production)
+* [Get Management API Tokens for Single-page Applications](/api/management/v2/get-access-tokens-for-spas)
+* [Applications](/applications)
+* [Management API Explorer](/api/management/v2#!)
+* [Management API Access Tokens FAQs](/api/management/v2/faq-management-api-access-tokens)
diff --git a/articles/api/management/v2/faq-management-api-access-tokens.md b/articles/api/management/v2/faq-management-api-access-tokens.md
new file mode 100644
index 0000000000..28600870ec
--- /dev/null
+++ b/articles/api/management/v2/faq-management-api-access-tokens.md
@@ -0,0 +1,33 @@
+---
+description: FAQs for Management API Access Tokens
+section: apis
+toc: true
+topics:
+ - apis
+ - management-api
+ - tokens
+contentType:
+ - reference
+useCase: invoke-api
+---
+
+# Management API Access Token FAQs
+
+__How long is the token valid for?__
+The Management API token has by default a validity of __24 hours__. After that the token will expire and you will have to get a new one. If you get one manually from [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer) though, you can change the expiration time. However, having non-expiring tokens is not secure.
+
+__The old way of generating tokens was better, since the token never expired. Why was this changed?__
+The old way of generating tokens was insecure since the tokens had an infinite lifespan. The new implementation allows tokens to be generated with specific scopes and expirations. We decided to move to the most secure implementation because your security, and that of your users, is priority number one for us.
+
+__Can I change my token's validity period?__
+You cannot change the default validity period, which is set to 24 hours. However, if you get a token manually from [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer) you can change the expiration time for the specific token. Note though, that your applications should use short-lived tokens to minimize security risks.
+
+__Can I refresh my token?__
+You cannot renew a Management API token. A [new token](#2-get-the-token) should be created when the old one expires.
+
+__My token was compromised! Can I revoke it?__
+You cannot directly revoke a Management API token, thus we recommend a short validity period.
+Note that deleting the application grant will prevent *new tokens* from being issued to the application. You can do this either by [using our API](/api/management/v2#!/Client_Grants/delete_client_grants_by_id), or manually [deauthorize the API application using the dashboard](${manage_url}/#/apis/management/authorized-applications).
+
+__My Client Secret was compromised! What should I do?__
+You need to change the secret immediately. Go to your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings) and click the __Rotate__ icon , or use the [Rotate a client secret](/api/management/v2#!/Clients/post_rotate_secret) endpoint. Note that previously issued tokens will continue to be valid until their expiration time.
diff --git a/articles/api/management/v2/get-access-tokens-for-production.md b/articles/api/management/v2/get-access-tokens-for-production.md
new file mode 100644
index 0000000000..fdb44e1706
--- /dev/null
+++ b/articles/api/management/v2/get-access-tokens-for-production.md
@@ -0,0 +1,180 @@
+---
+description: How to get Access Tokens to make scheduled frequent calls to the Management API.
+section: apis
+toc: true
+topics:
+ - apis
+ - management-api
+ - tokens
+contentType:
+ - how-to
+useCase: invoke-api
+---
+
+# Get Access Tokens for Production
+
+To make scheduled frequent calls for a production environment, you have to build a process at your backend that will provide you with a token automatically (and thus simulate a non-expiring token).
+
+## Prerequisite
+
+* [Create and Authorize a Machine-to-Machine Application](/api/management/v2/create-m2m-app).
+
+## Get Access Tokens
+
+To ask Auth0 for a Management API v2 token, perform a `POST` operation to the `https://${account.namespace}/oauth/token` endpoint, using the credentials of the Machine-to-Machine Application you created in the prerequisite step.
+
+The payload should be in the following format:
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData": {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "client_credentials"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "audience",
+ "value": "https://${account.namespace}/api/v2/"
+ }
+ ]
+ }
+}
+```
+
+The request parameters are:
+
+| __Request Parameter__ | __Description__ |
+| ------ | ----------- |
+| __grant_type__ | Denotes which [OAuth 2.0 flow](/protocols/oauth2#authorization-grant-types) you want to run. For machine to machine communication use the value `client_credentials`. |
+| __client_id__ | This is the value of the __Client ID__ field of the Machine-to-Machine Application you created. You can find it on the [Settings tab of your Application](${manage_url}/#/applications/${account.clientId}/settings). |
+| __client_secret__ | This is the value of the __Client Secret__ field of the Machine-to-Machine Application you created. You can find it at the [Settings tab of your Application](${manage_url}/#/applications/${account.clientId}/settings). |
+| __audience__ | This is the value of the __Identifier__ field of the `Auth0 Management API`. You can find it at the [Settings tab of the API](${manage_url}/#/apis). |
+
+The response will contain a [signed JWT](/tokens/concepts/jwts), when it expires, the scopes granted, and the token type.
+
+```json
+{
+ "access_token": "eyJ...Ggg",
+ "expires_in": 86400,
+ "scope": "read:clients create:clients read:client_keys",
+ "token_type": "Bearer"
+}
+```
+
+From the above we can see that our Access Token is a [Bearer Access Token](https://tools.ietf.org/html/rfc6750), it will expire in 24 hours (86400 seconds), and it has been authorized to read and create applications.
+
+### Use Auth0's Node.js Client Library
+
+As an alternative to making HTTP calls, you can use the [node-auth0](https://www.npmjs.com/package/auth0) library to automatically [obtain tokens for the Management API](https://www.npmjs.com/package/auth0#user-content-management-api-client).
+
+## Use Access Tokens
+
+To use this token, include it in the `Authorization` header of your request.
+
+```har
+{
+ "method": "POST",
+ "url": "http://PATH_TO_THE_ENDPOINT/",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer YOUR_ACCESS_TOKEN"}
+ ]
+}
+```
+
+For example, in order to [Get all applications](/api/management/v2#!/Clients/get_clients) use the following:
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/clients",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik5ESTFNa05DTVRGQlJrVTRORVF6UXpFMk1qZEVNVVEzT1VORk5ESTVSVU5GUXpnM1FrRTFNdyJ9.eyJpc3MiOiJodHRwczovL2RlbW8tYWNjb3VudC5hdXRoMC5jb20vIiwic3ViIjoib9O7eVBnMmd4VGdMNjkxTnNXY2RUOEJ1SmMwS2NZSEVAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vZGVtby1hY2NvdW50LmF1dGgwLmNvbS9hcGkvdjIvIiwiZXhwIjoxNDg3MDg2Mjg5LCJpYXQiOjE5ODY5OTk4ODksInNjb3BlIjoicmVhZDpjbGllbnRzIGNyZWF0ZTpjbGllbnRzIHJlYWQ6Y2xpZW50X2tleXMifQ.oKTT_cEA_U6hVzNYPCl_4-SnEXXvFSOMJbZyFydQDPml2KqBxVw_UPAXhjgtW8Kifc_b2HQ4jFh7nH0KC_j1XjfEJPvwFZgqfI_ILzO3DPfpEIK_n_aX-Tz4okbZe6nj2aT_qLpHimLxK50jOGaMuzp4a1djHJTj5q-NbIiPW8AJowS2-gveP4T3dyyegUsZkmTNwrreqppPApmpWWE-wVsxnVsI_FZFrHnq0rn7lmY_Iz6vyiZjaKrd2C3hFm0zFGTn8FslBfHUldTcDNzOKOpCq7HFMeU0urXBXDetrzkW1afxIqED3G2C51JEV-4nTRYUinnWgXJfLJ87G3ge_A"}
+ ]
+}
+```
+
+::: note
+You can get the curl command for each endpoint from the Management API v2 Explorer. Go to the endpoint you want to call, and click the __get curl command__ link at the __Test this endpoint__ section.
+:::
+
+## Example: Python Implementation
+
+This python script gets a Management API v2 Access Token, uses it to call the [Get all applications](/api/management/v2#!/Clients/get_clients) endpoint, and prints the response in the console.
+
+Before you run it make sure that the following variables hold valid values:
+- `audience`: The __Identifier__ of the `Auth0 Management API`. You can find it at the [Settings tab of the API](${manage_url}/#/apis).
+- `domain`: The __Domain__ of the Machine-to-Machine Application you created.
+- `client_id`: The __Client ID__ of the Machine to Machine Application you created.
+- `client_secret`: The __Client Secret__ of the Machine-to-Machine Application you created.
+
+```python
+def main():
+ import json, requests
+ from requests.exceptions import RequestException, HTTPError, URLRequired
+
+ # Configuration Values
+ audience = f"https://${account.namespace}/api/v2/"
+ domain = "${account.namespace}"
+ client_id = "${account.clientId}"
+ client_secret = "YOUR_CLIENT_SECRET"
+ grant_type = "client_credentials" # OAuth 2.0 flow to use
+
+ # Get an Access Token from Auth0
+ base_url = f"https://{domain}"
+ payload = {'grant_type': 'client_credentials',
+ 'client_id': client_id,
+ 'client_secret': client_secret,
+ 'audience': audience}
+ res = requests.get(base_url, data=payload)
+ oauth = json.loads(response.json())
+ access_token = oauth.get('access_token')
+
+ # Get all Applications using the token
+ res = requests.get(base_url + "/api/v2/clients")
+ header = {
+ 'Authorization', 'Bearer ' + access_token,
+ 'Content-Type', 'application/json'
+ }
+
+ try:
+ res = request.get(req, header = header)
+ output = json.loads(res.json())
+ print(output)
+ except HTTPError as e:
+ print('HTTPError = ' + str(e.code) + ' ' + str(e.reason))
+ except URLRequired as e:
+ print(f'URLRequired = str(e.reason)')
+ except RequestException as e:
+ print('RequestException: {e}')
+ except Exception as e:
+ print(f'Generic Exception: {e}')
+
+# Standard boilerplate to call the main() function.
+if __name__ == '__main__':
+ main()
+```
+
+## Keep reading
+
+- [Applications](/applications)
+* [Management API Explorer](/api/management/v2#!)
+* [Management API Access Tokens FAQs](/api/management/v2/faq-management-api-access-tokens)
+
+
diff --git a/articles/api/management/v2/get-access-tokens-for-spas.md b/articles/api/management/v2/get-access-tokens-for-spas.md
new file mode 100644
index 0000000000..49f58e6168
--- /dev/null
+++ b/articles/api/management/v2/get-access-tokens-for-spas.md
@@ -0,0 +1,60 @@
+---
+description: Describes available scopes and endpoints for Management API tokens for Single-page Applications (SPAs).
+section: apis
+topics:
+ - apis
+ - management-api
+ - tokens
+contentType:
+ - how-to
+useCase: invoke-api
+---
+
+# Get Management API Tokens for Single-page Applications
+
+In certain cases, you may want to use Auth0's [Management API](/api/management/v2#!) to manage your applications and APIs rather than the Auth0 Management Dashboard.
+
+To call any Management API endpoints, you must authenticate using a specialized [Access Token](/tokens/overview-access-tokens) called the Management API Token. Management API Tokens are [JSON Web Tokens (JWTs)](/tokens/concepts/jwts) that contain specific granted permissions (also known as scopes) for the Management API endpoints you want to call.
+
+## Limitations
+
+Since single-page applications (SPAs) are public clients and cannot securely store sensitive information (such as a **Client Secret**), they must retrieve Management API Tokens from the frontend, unlike other [application types](/applications). This means that Management API Tokens for SPAs have certain limitations. Specifically, they are issued in the context of the user who is currently signed in to Auth0 which limits updates to only the logged-in user's data. Although this restricts use of the Management API, it can still be used to perform actions related to updating the logged-in user's user profile.
+
+::: warning
+Auth0 does not recommend putting Management API Tokens on the frontend that allow users to change user metadata. This can allow users to manipulate their own metadata in a way that could be detrimental to the functioning of the applications. It also allows a customer to do a DoS attack against someone's management API by just spamming it and hitting rate limits.
+:::
+
+## Available scopes and endpoints
+
+With a Management API Token issued for a SPA, you can access the following scopes (and hence endpoints).
+
+::: note
+Password changes through the [PATCH /api/v2/users/{id}](/api/management/v2#!/Users/patch_users_by_id) endpoint are **not possible** with a Management API Token issued for a SPA.
+:::
+
+| **Scope for Current User** | **Endpoint** |
+| -------------------------- | ------------ |
+| `read:current_user` | [GET /api/v2/users/{id}](/api/management/v2#!/Users/get_users_by_id) [GET /api/v2/users/{id}/enrollments](/api/management/v2#!/Users/get_enrollments) |
+| `update:current_user_identities` | [POST/api/v2/users/{id}/identities](/api/management/v2#!/Users/post_identities) [DELETE /api/v2/users/{id}/identities/{provider}/{user_id}](/api/management/v2#!/Users/delete_user_identity_by_user_id) |
+| `update:current_user_metadata` | [PATCH /api/v2/users/{id}](/api/management/v2#!/Users/patch_users_by_id) |
+| `create:current_user_metadata` | [PATCH /api/v2/users/{id}](/api/management/v2#!/Users/patch_users_by_id) |
+| `delete:current_user_metadata` | [DELETE /api/v2/users/{id}/multifactor/{provider}](/api/management/v2#!/Users/delete_multifactor_by_provider) |
+| `create:current_user_device_credentials` | [POST /api/v2/device-credentials](/api/management/v2#!/Device_Credentials/post_device_credentials) |
+| `delete:current_user_device_credentials` | [DELETE /api/v2/device-credentials/{id}](/api/management/v2#!/Device_Credentials/delete_device_credentials_by_id) |
+
+::: note
+The above scopes and endpoints are subject to [rate limits](/policies/rate-limits#access-tokens-for-spas).
+:::
+
+## Use Management API Token to call Management API from a SPA
+
+You can retrieve a Management API Token from a SPA and use the token to call the Management API to retrieve the full user profile of the currently logged-in user.
+
+1. Retrieve a Management API token. Authenticate the user by redirecting them to the Authorization endpoint, which is where users are directed upon login or sign-up. When you receive the Management API Token, it will be in [JSON Web Token format](/tokens/references/jwt-structure). Decode it and review its contents.
+
+2. Call the Management API to retrieve the logged-in user's user profile from the [Get User by ID](/api/management/v2#!/Users/get_users_by_id) endpoint. To call the endpoint, include the encoded Management API Token you retrieved in the `Authorization` header of the request. Be sure to replace the `USER_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with the logged-in user's user ID (`sub` value from the decoded Management API Token) and the Management API Access Token, respectively.
+
+## Keep reading
+
+* [Management API Explorer](/api/management/v2#!)
+* [Management API Access Tokens FAQs](/api/management/v2/faq-management-api-access-tokens)
diff --git a/articles/api/management/v2/get-access-tokens-for-test.md b/articles/api/management/v2/get-access-tokens-for-test.md
new file mode 100644
index 0000000000..ad6a3e6b1b
--- /dev/null
+++ b/articles/api/management/v2/get-access-tokens-for-test.md
@@ -0,0 +1,58 @@
+---
+description: How to get an Access Token manually for testing purposes.
+section: apis
+toc: true
+topics:
+ - apis
+ - management-api
+ - tokens
+contentType:
+ - How-to
+useCase: invoke-api
+---
+
+# Get Access Tokens for Testing
+
+::: warning
+This method for obtaining Access Tokens is **only for test purposes**. Do not get manually long-lived tokens and use them in your applications, because that nullifies the security advantages that tokens offer.
+:::
+
+## Prerequisite
+
+* [Create and Authorize a Machine-to-Machine Application](/api/management/v2/create-m2m-app).
+
+## Get Access Tokens Manually
+
+1. Go to [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer).
+A token is automatically generated and displayed there.
+
+2. Click __Copy Token__.
+You can now make authorized calls to the [Management API](/api/management/v2) using this token.
+
+
+
+3. Set expiration time.
+This token has, by default, an expiration time of __24 hours__ (86400 seconds). After that period, the token expires and you will need to get a new one. To change the expiration time, update the __Token Expiration (Seconds)__ field and click __Update & Regenerate Token__.
+
+:::warning
+These tokens **cannot be revoked** so long expiration times are not recommended. Instead we recommend that you use short expiration times and issue a new one every time you need it.
+:::
+
+## Use Access Tokens for Testing
+
+To use the Access Token you just created for testing purposes, use the [Management API v2 explorer page](/api/management/v2) to manually call an endpoint with the token.
+
+1. Go to the [Management API v2 explorer page](/api/management/v2#!).
+1. Click the __Set API Token__ button at the top left.
+1. Set the __API Token__ field, and click __Set Token__.
+1. Under the __Set API Token__ button at the top left, some new information is now displayed: the domain and token set, and the scopes that have been granted to this application.
+1. Go to the endpoint you want to call, fill any parameters that might be required and click __Try__.
+
+
+
+## Keep reading
+
+* [Get Access Tokens for Production](/api/management/v2/get-access-tokens-for-production)
+- [Applications](/applications)
+* [Management API Explorer](/api/management/v2#!)
+* [Management API Access Tokens FAQs](/api/management/v2/faq-management-api-access-tokens)
diff --git a/articles/api/management/v2/tokens-flows.md b/articles/api/management/v2/tokens-flows.md
index 34a30b219b..18ddec7612 100644
--- a/articles/api/management/v2/tokens-flows.md
+++ b/articles/api/management/v2/tokens-flows.md
@@ -3,133 +3,47 @@ description: Describes what changed in the flow for generating Auth0 Management
section: apis
crews: crew-2
toc: true
+topics:
+ - apis
+ - management-api
+ - tokens
+contentType: concept
+useCase: invoke-api
---
# Changes in Auth0 Management APIv2 Tokens
-Some time ago we changed the process to get a Management APIv2 Token. This article explains what changed, why this was done and how you can work around it (not recommended).
+Some time ago, we changed the process of getting a Management APIv2 Token. This article explains what changed, why this was done, and how you can work around it (not recommended).
## What changed and why
### The User Experience
-Until recently you could generate a Management APIv2 Token directly from the Management API explorer. You selected the scopes, according to the endpoint you wanted to invoke, and got a token from that same page.
+Until recently, you could generate a Management APIv2 Token directly from the Management API explorer. You selected the scopes, according to the endpoint you wanted to invoke, and got a token from that same page.
That way was very easy but it was also __very insecure__. So we changed it.
-The new way uses the [OAuth 2.0 Client Credentials grant](/api-auth/grant/client-credentials).
-
-You can get a new token either [using the dashboard](/api/management/v2/tokens#get-a-token-manually) (if you use the API sporadically) or [by configuring a server process](/api/management/v2/tokens#automate-the-process) (if you need a token frequently) that will get a new token every 24 hours.
+The new way uses the [Client Credentials Flow](/flows/concepts/client-credentials).
::: note
-For details on how to follow this new process refer to [The Auth0 Management APIv2 Token](/api/management/v2/tokens).
+For details on how to follow this new process, see [Access Tokens for the Management API](/api/management/v2/tokens).
:::
#### Why this changed
-In order to generate the token, the Management API required access to your __Global Client Secret__ (used to sign the token). This is information that should __not__ be exposed to web browsers.
+To generate the token, the Management API required access to your __Global Client Secret__ (used to sign the token). This is information that should __not__ be exposed to web browsers.
-Furthermore, the API Explorer has no way to do authorization. This means that if you could login and access the API explorer, you could generate a token with __any__ scope, even if you as the logged in user were not allowed to have that scope.
+Furthermore, the API Explorer has no way to do authorization. This means that if a user could login and access the API explorer, they could generate a token with __any__ scope, even if they were not allowed to have that scope.
The new OAuth 2.0 Client Credentials grant implementation does not pose such risks. Once you do the initial configuration, you can get a token either by visiting the dashboard, or by making a simple `POST` request to [the `/oauth/token` endpoint of our Authentication API](/api/authentication#client-credentials).
However, with regards to the manual process, we do understand that changing screens is not always the best user experience, so we are looking into ways to make the new flow more intuitive.
-
### The Validity Period
-With the previous flow the tokens never expired. With the new flow all Management APIv2 Tokens __expire by default after 24 hours__. You can [work around that](#can-i-still-get-a-non-expiring-token-), even though we do not recommend it.
+With the previous flow, the tokens never expired. With the new flow, all Management APIv2 Tokens __expire by default after 24 hours__.
#### Why this changed
Having a token that never expires can be very risky, in case an attacker gets hold of it. If the token expires within a few hours the attacker has only a small window to access your protected resources.
-## Can I still get a non-expiring token?
-
-Yes you can. We added a text box (__Token Expiration (Seconds)__), at [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer), where you can set the new expiration time (in seconds) and click __Update & Regenerate Token__. A new token will be generated with your custom expiration time. Our recommendation however is not to use this and get a new token every 24 hours. You can easily automate this [following this process](/api/management/v2/tokens#1-get-a-token).
-
-Furthermore, you can generate a token using [JWT.io](https://jwt.io/):
-- Use the [JWT.io Debugger](https://jwt.io/#debugger-io) to manually type the claims and generate a token.
-- Use one of the [JWT.io libraries](https://jwt.io/#libraries-io).
-
-::: warning
-Long-lived tokens compromise your security. Following this process is NOT recommended.
-:::
-
-### Use the JWT.io Debugger
-
-You can use the [JWT.io Debugger](https://jwt.io/#debugger-io) to manually generate a token.
-
-The debugger allows you to edit the __Header__ and __Payload__ content on the right hand side of the screen. The token will automatically be updated on the left hand text area. Note that the debugger supports only `HS256` when editing header and payload.
-
-To generate a token follow the next steps:
-
-1. Go to [JWT.io Debugger](https://jwt.io/#debugger-io). Notice that there is a sample token on the left hand editor. The right hand editor contains the header, payload and verify signature parts.
-
-2. Delete the dummy `secret` value from the _Verify Signature_ panel. Set your __Global Client Secret__ (you can find this value at [Advanced Tenant Settings](${manage_url}/#/tenant/advanced)) and check the __secret base64 encoded__ flag.
-
-3. Make sure the _Header_ contains the `alg` and `typ` claims, as follows.
-
- ```json
- {
- "alg": "HS256",
- "typ": "JWT"
- }
- ```
-4. Delete the dummy claims from the _Payload_ and add the following claims: `iss`, `aud`, `scope`, `iat`, `exp`.
-
- ```json
- {
- "iss": "https://${account.namespace}/",
- "aud": "YOUR_GLOBAL_CLIENT_ID",
- "scope": "SPACE-SEPARATED-LIST-OF-SCOPES",
- "iat": CURRENT_TIMESTAMP,
- "exp": EXPIRY_TIME
- }
- ```
-
- Where:
-
- - __iss__: Who issued the token. Use your tenant's __Domain__. You can find this value at any [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings).
-
- - __aud__: Who is the intended audience for this token. Use the __Global Client Id__ of your tenant. You can find this value at [Advanced Tenant Settings](${manage_url}/#/tenant/advanced).
-
- - __scope__: The (space separated) list of authorized scopes for the token. Each [Auth0 Management API v2](/api/management/v2) endpoint requires specific scopes. For example, the [Get all applications](/api/management/v2#!/Clients/get_clients) endpoint requires the scopes `read:clients` and `read:client_keys`, while the [Create an application](/api/management/v2#!/Clients/post_clients) endpoint requires the scope `create:clients`. So if you need to read _and_ create applications, then the token should include three scopes: `read:clients`, `read:client_keys` and `create:clients`. In this case you would set the scope at the editor to the value `read:clients read:client_keys create:clients`.
-
- - __iat__: The time at which the token was issued. It must be a number containing a `NumericDate` value, for example `1487260214` (which maps to `Thu, 16 Feb 2017 15:50:14 GMT`). You can use an [epoch converter](http://www.epochconverter.com/) to get this value.
-
- - __exp__: The time at which the token will expire. It must be a number containing a `NumericDate` value, for example `1518808520` (which maps to `Fri, 16 Feb 2018 19:15:20 GMT`).
-
-5. As you type the token on the left hand editor is automatically refreshed. When you are done copy this value.
-
-### Use a Library
-
-- Use one of the [JWT.io libraries](https://jwt.io/#libraries-io). For example, the following snippet generates a JWT using [node-jsonwebtoken](https://github.com/auth0/node-jsonwebtoken):
-
- ```javascript
- const jwt = require('jsonwebtoken');
- const globalClientSecret = new Buffer('YOUR_GLOBAL_CLIENT_SECRET', 'base64');
- const currentTimestamp = Math.floor(new Date());
-
- var token = jwt.sign({
- iss: 'https://${account.namespace}/',
- aud: 'YOUR_GLOBAL_CLIENT_ID',
- scope: 'read:clients read:client_keys'},
- globalClientSecret,
- { //options
- algorithm: 'HS256',
- expiresIn: '1y'
- }
- );
-
- console.log(token);
- ```
-
- Note the following:
-
- - The token is signed using `HS256` and the __Global Client Secret__ (you can find this value at [Advanced Tenant Settings](${manage_url}/#/tenant/advanced)).
-
- - The audience (claim `aud`) is the __Global Client Id__ (you can find this value at [Advanced Tenant Settings](${manage_url}/#/tenant/advanced)).
-
- - We want this token in order to call the [Get all applications](/api/management/v2#!/Clients/get_clients) so we only asked for the scopes required by this endpoint: `read:clients read:client_keys`.
-
- - The token expires in one year (`expiresIn: '1y'`).
+To get a token, you should follow only the process described in [Access Tokens for the Management API](/api/management/v2/tokens).
diff --git a/articles/api/management/v2/tokens.md b/articles/api/management/v2/tokens.md
index 4714b8e9e2..4d99886e40 100644
--- a/articles/api/management/v2/tokens.md
+++ b/articles/api/management/v2/tokens.md
@@ -1,241 +1,38 @@
---
-description: Details on how to generate and use a token for the Auth0 Management APIv2
+description: Overview of how Auth0 Management APIv2 Access Tokens work and how to use them.
section: apis
-crews: crew-2
-toc: true
+topics:
+ - apis
+ - management-api
+ - tokens
+contentType:
+ - concept
+useCase: invoke-api
---
-# The Auth0 Management APIv2 Token
-In order to call the endpoints of [Auth0 Management API v2](/api/management/v2), you need a token, what we refer to as __Auth0 Management APIv2 Token__. This token is a [JWT](/jwt), it contains specific granted permissions (known as __scopes__), and it is signed with an application API key and secret for the entire tenant.
+# Access Tokens for the Management API
-There are two ways to get a Management APIv2 Token:
-- [get one manually using the Dashboard](#get-a-token-manually), or
-- [automate the process](#automate-the-process) (build a simple command line tool that generates tokens).
+To call the [Auth0 Management API v2](/api/management/v2) endpoints, you need to authenticate with a token called the __Auth0 Management API Token__. This token is a JSON Web Token (JWT) and it contains specific granted permissions (known as __scopes__).
-In this article we will see how you can do either.
+To call an endpoint for test purposes, you can get a token manually using the Dashboard. For production however, the recommended best practice is to get short-lived tokens programmatically.
-## Get a token manually
+To call endpoints, you will need to do the following:
-::: warning
-Τhe Management APIv2 token, by default, has a validity of __24 hours__. After that the token will expire and you will have to get a new one. If this doesn't work for you, you can either [change the validity period of the token](#2-get-the-token), or [automate the process](#automate-the-process). Keep in mind that these tokens **cannot be revoked** so long expiration times are **not recommended**.
-:::
-
-Let's see how you can get a token manually. Note, that the first step of the process need to be executed _only_ the first time.
-
-### 1. Create and Authorize an Application
-
-First, you need to create and authorize a Machine to Machine Application. We recommend creating one exclusively for authorizing access to the Management API, instead of reusing another one you might have. If you already have done that, you can skip this paragraph.
-
-::: panel What is a Machine to Machine Application?
-A Machine to Machine Application represents a program that interacts with an API where there is no user involved. An example would be a server script that would be granted access to consume a Zip Codes API. It's a machine to machine interaction. This must be used instead of a Single Page or Native apps because those cannot meet the necessary security requirements for executing this type of flow. If you want to read more about calling APIs this way, refer to [Calling APIs from a Service](/api-auth/grant/client-credentials).
-:::
-
-To create and authorize a Machine to Machine Application for the Management API, go to [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer).
-
-Click the button __Create & Authorize a Test Application__.
-
-
-
-That's it! A new application has been created and it's authorized to access the Management API.
-
-Note, that each Machine to Machine Application that accesses an API, has to be granted a set of scopes. This application that we just created has been granted __all__ the APIv2 scopes. This means that it can access all the endpoints.
-
-::: panel What are the scopes?
-The scopes are permissions that should be granted by the owner. Each [Auth0 Management API v2](/api/management/v2) endpoint requires specific scopes. For example, the [Get all applications](/api/management/v2#!/Clients/get_clients) endpoint requires the scopes `read:clients` and `read:client_keys`, while the [Create an application](/api/management/v2#!/Clients/post_clients) endpoint requires the scope `create:clients`. From that we can deduce that if we need to read _and_ create applications, then our token should include three scopes: `read:clients`, `read:client_keys` and `create:clients`.
-:::
+* [Create and Authorize a Machine-to-Machine Application](/api/management/v2/create-m2m-app)
+* [Get Access Tokens for Testing](/api/management/v2/get-access-tokens-for-test)
+* [Get Access Tokens for Production](/api/management/v2/get-access-tokens-for-production)
::: note
-If you have multiple apps that should access the Management API, and you need different sets of scopes per app, we recommend creating a new Machine to Machine Application for each. For example, if one app is to read and create users (`create:users`, `read:users`) and another to read and create applications (`create:clients`, `read:clients`) create two Applications (one for user scopes, one for applications) instead of one.
+For single-page applications (SPAs), there are some limitations. See [Get Management API Tokens for SPAs](/api/management/v2/get-access-tokens-for-spas) for more information.
:::
-### 2. Get the Token
-
-A token is automatically generated and displayed at [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer).
-
-Note, that this token has by default an expiration time of 24 hours (86400 seconds). To change that, update the __Token Expiration (Seconds)__ field and click __Update & Regenerate Token__.
-
-
-
-Click __Copy Token__. You can now make authorized calls to the [Management API v2](/api/management/v2) using this token.
-
-### 3. Use the Token
-
-You can use the [Management API v2 explorer page](/api/management/v2) to manually call an endpoint, using the token you got in the previous step. You will need:
-- The Management API v2 token you just got.
-- Your tenant's domain (`${account.namespace}`). You can find this on the _Settings_ of any of your [Applications](${manage_url}/#/applications/${account.clientId}/settings).
-
-Once you have this information you are ready to call the API. Follow these steps:
-1. Go to the [Management API v2 explorer page](/api/management/v2)
-1. Click the __Set API Token__ button at the top left
-1. Set the __Domain__ and __API Token__ fields, and click __Set Token__
-1. Under the __Set API Token__ button at the top left, some new information is now displayed: the domain and token set, and the scopes that have been granted to this application
-1. Go to the endpoint you want to call, fill any parameters that might be required and click __Try__
-
-
-
-## Automate the Process
-
-[The manual process](#get-a-token-manually) might work for you if you want to test an endpoint or invoke it sporadically. But if you need to make scheduled frequent calls then you have to build a simple CLI that will provide you with a token automatically (and thus simulate a non-expiring token).
-
-::: panel Prerequisites
-Before you proceed with the implementation, you must have [created and authorized a Machine to Machine Application](#1-create-and-authorize-an-application). The Application should have all the required scopes for the endpoints you mean to access.
-:::
-
-### 1. Get a Token
-
-To ask Auth0 for a Management API v2 token, perform a `POST` operation to the `https://${account.namespace}/oauth/token` endpoint, using the credentials of the Machine to Machine Application you created at [this step](#1-create-and-authorize-an-application).
-
-The payload should be in the following format:
-
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/oauth/token",
- "headers": [
- { "name": "Content-Type", "value": "application/json" }
- ],
- "postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"client_credentials\",\"client_id\": \"${account.clientId}\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"audience\": \"https://${account.namespace}/api/v2/\"}"
- }
-}
-```
-
-The request parameters are:
-- `grant_type`: Denotes which [OAuth 2.0 flow](/protocols/oauth2#authorization-grant-types) you want to run. For machine to machine communication use the value `client_credentials`.
-- `client_id`: This is the value of the __Client ID__ field of the Machine to Machine Application you created at [this step](#1-create-an-application). You can find it at the [Settings tab of your Application](${manage_url}/#/applications/${account.clientId}/settings).
-- `client_secret`: This is the value of the __Client Secret__ field of the Machine to Machine Application you created at [this step](#1-create-an-application). You can find it at the [Settings tab of your Application](${manage_url}/#/applications/${account.clientId}/settings).
-- `audience`: This is the value of the __Identifier__ field of the `Auth0 Management API`. You can find it at the [Settings tab of the API](${manage_url}/#/apis).
-
-The response will contain a [signed JWT (JSON Web Token)](/jwt), when it expires, the scopes granted, and the token type.
-
-```json
-{
- "access_token": "eyJ...Ggg",
- "expires_in": 86400,
- "scope": "read:clients create:clients read:client_keys",
- "token_type": "Bearer"
-}
-```
-
-From the above we can see that our `access_token` is a [bearer Access Token](https://tools.ietf.org/html/rfc6750), it will expire in 24 hours (86400 seconds), and it has been authorized to read and create applications.
-
-### 2. Use the Token
-
-To use this token, just include it in the `Authorization` header of your request .
-
-```har
-{
- "method": "POST",
- "url": "http://PATH_TO_THE_ENDPOINT/",
- "headers": [
- { "name": "Content-Type", "value": "application/json" },
- { "name": "Authorization", "value": "Bearer YOUR_ACCESS_TOKEN"}
- ]
-}
-```
-
-For example, in order to [Get all applications](/api/management/v2#!/Clients/get_clients) use the following:
-
-```har
-{
- "method": "GET",
- "url": "https://${account.namespace}/api/v2/clients",
- "headers": [
- { "name": "Content-Type", "value": "application/json" },
- { "name": "Authorization", "value": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik5ESTFNa05DTVRGQlJrVTRORVF6UXpFMk1qZEVNVVEzT1VORk5ESTVSVU5GUXpnM1FrRTFNdyJ9.eyJpc3MiOiJodHRwczovL2RlbW8tYWNjb3VudC5hdXRoMC5jb20vIiwic3ViIjoib9O7eVBnMmd4VGdMNjkxTnNXY2RUOEJ1SmMwS2NZSEVAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vZGVtby1hY2NvdW50LmF1dGgwLmNvbS9hcGkvdjIvIiwiZXhwIjoxNDg3MDg2Mjg5LCJpYXQiOjE5ODY5OTk4ODksInNjb3BlIjoicmVhZDpjbGllbnRzIGNyZWF0ZTpjbGllbnRzIHJlYWQ6Y2xpZW50X2tleXMifQ.oKTT_cEA_U6hVzNYPCl_4-SnEXXvFSOMJbZyFydQDPml2KqBxVw_UPAXhjgtW8Kifc_b2HQ4jFh7nH0KC_j1XjfEJPvwFZgqfI_ILzO3DPfpEIK_n_aX-Tz4okbZe6nj2aT_qLpHimLxK50jOGaMuzp4a1djHJTj5q-NbIiPW8AJowS2-gveP4T3dyyegUsZkmTNwrreqppPApmpWWE-wVsxnVsI_FZFrHnq0rn7lmY_Iz6vyiZjaKrd2C3hFm0zFGTn8FslBfHUldTcDNzOKOpCq7HFMeU0urXBXDetrzkW1afxIqED3G2C51JEV-4nTRYUinnWgXJfLJ87G3ge_A"}
- ]
-}
-```
-
-::: note
- You can get the curl command for each endpoint from the Management API v2 Explorer. Go to the endpoint you want to call, and click the get curl command link at the Test this endpoint section.
-:::
-
-That's it! You are done!
-
-### Sample Implementation: Python
-
-This python script gets a Management API v2 Access Token, uses it to call the [Get all applications](/api/management/v2#!/Clients/get_clients) endpoint, and prints the response in the console.
-
-Before you run it make sure that the following variables hold valid values:
-- `AUDIENCE`: The __Identifier__ of the `Auth0 Management API`. You can find it at the [Settings tab of the API](${manage_url}/#/apis).
-- `DOMAIN`: The __Domain__ of the Machine to Machine Application you created at [this step](#1-create-an-application).
-- `CLIENT_ID`: The __Client ID__ of the Machine to Machine Application you created at [this step](#1-create-an-application).
-- `CLIENT_SECRET`: The __Client Secret__ of the Machine to Machine Application you created at [this step](#1-create-an-application).
-
-```python
-def main():
- import json, urllib, urllib2
-
- # Configuration Values
- AUDIENCE = "https://${account.namespace}/api/v2/"
- DOMAIN = "${account.namespace}"
- CLIENT_ID = "${account.clientId}"
- CLIENT_SECRET = "YOUR_CLIENT_SECRET"
- GRANT_TYPE = "client_credentials" # OAuth 2.0 flow to use
-
- # Get an Access Token from Auth0
- base_url = "https://{domain}".format(domain=DOMAIN)
- data = urllib.urlencode([('client_id', CLIENT_ID),
- ('client_secret', CLIENT_SECRET),
- ('audience', AUDIENCE),
- ('grant_type', GRANT_TYPE)])
- req = urllib2.Request(base_url + "/oauth/token", data)
- response = urllib2.urlopen(req)
- oauth = json.loads(response.read())
- access_token = oauth['access_token']
-
- # Get all Applications using the token
- req = urllib2.Request(base_url + "/api/v2/clients")
- req.add_header('Authorization', 'Bearer ' + access_token)
- req.add_header('Content-Type', 'application/json')
-
- try:
- response = urllib2.urlopen(req)
- res = json.loads(response.read())
- print res
- except urllib2.HTTPError, e:
- print 'HTTPError = ' + str(e.code) + ' ' + str(e.reason)
- except urllib2.URLError, e:
- print 'URLError = ' + str(e.reason)
- except urllib2.HTTPException, e:
- print 'HTTPException'
- except Exception:
- print 'Generic Exception'
-
-# Standard boilerplate to call the main() function.
-if __name__ == '__main__':
- main()
-```
-
-## Frequently Asked Questions
-
-__How long is the token valid for?__
-The Management APIv2 token has by default a validity of __24 hours__. After that the token will expire and you will have to get a new one. If you get one manually from [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer) though, you can change the expiration time. However, having non-expiring tokens is not secure.
-
-__The old way of generating tokens was better, since the token never expired. Why was this changed?__
-The old way of generating tokens was insecure since the tokens had an infinite lifespan. The new implementation allows tokens to be generated with specific scopes and expirations. We decided to move to the most secure implementation because your security, and that of your users, is priority number one for us.
-
-__Can I change my token's validity period?__
-You cannot change the default validity period, which is set to 24 hours. However, if you get a token manually from [the API Explorer tab of your Auth0 Management API](${manage_url}/#/apis/management/explorer) you can change the expiration time for the specific token. Note though, that your applications should use short-lived tokens to minimize security risks.
-
-__Can I refresh my token?__
-You cannot renew a Management APIv2 token. A [new token](#2-get-the-token) should be created when the old one expires.
-
-__My token was compromised! Can I revoke it?__
-You cannot directly revoke a Management APIv2 token, thus we recommend a short validity period.
-Note that deleting the application grant will prevent *new tokens* from being issued to the application. You can do this either by [using our API](/api/management/v2#!/Client_Grants/delete_client_grants_by_id), or manually [deauthorize the APIv2 application using the dashboard](${manage_url}/#/apis/management/authorized-applications).
-
-__My Client Secret was compromised! What should I do?__
-You need to change the secret immediately. Go to your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings) and click the __Rotate__ icon , or use the [Rotate a client secret](/api/management/v2#!/Clients/post_rotate_secret) endpoint. Note that previously issued tokens will continue to be valid until their expiration time.
-
## Keep reading
-::: next-steps
-* [Changes in Auth0 Management APIv2 Tokens](/api/management/v2/tokens-flows)
-* [Calling APIs from a Service](/api-auth/grant/client-credentials)
+* [Access Tokens](/tokens/concepts/access-tokens)
+* [Management API Access Token FAQs](/api/management/v2/faq-management-api-access-tokens)
+* [Changes in Auth0 Management API Tokens](/api/management/v2/tokens-flows)
+* [Client Credentials Flow](/flows/concepts/client-credentials)
* [Ask for Access Tokens for a Client Credentials Grant](/api-auth/config/asking-for-access-tokens)
-* [Information on the query string syntax](/api/management/v2/query-string-syntax)
-* [Search for Users](/api/management/v2/user-search)
-:::
+* [User Search](/users/search)
+* [User Search Query Syntax](/users/search/v3/query-syntax)
+
diff --git a/articles/api/postman.md b/articles/api/postman.md
index 699205d5e7..7bdcb17983 100644
--- a/articles/api/postman.md
+++ b/articles/api/postman.md
@@ -1,57 +1,61 @@
---
-desription: This page explains how to use Postman Collections to access Auth0 APIs.
+description: Learn how to use Postman Collections to access Auth0 APIs.
section: apis
+topics:
+ - management-api
+ - authorization-api
+ - apis
+contentType: how-to
+useCase: invoke-api
---
-# Using the Auth0 API with our Postman Collections
+# Use Auth0 APIs with Postman Collections
-## Installing the Collections
+## Install Postman Collections
-To install the Postman Collection you will need to have installed the Postman App for Windows, Mac or Chrome. You can download any of these from the [Postman Apps page](https://www.getpostman.com/apps).
+To install the Postman Collection, you must first install the Postman App for Windows, Mac, or Chrome. You can download any of these from[Postman Apps](https://www.getpostman.com/apps).
-Next, head over to our new [API Landing Page](/api/info), and install the Collection you want to use by clicking on the relevant "Run in Postman" button.
+Next, visit [Auth0 APIs](/api/info) and install the Collection you want to use by clicking on the relevant **Run in Postman** button.
-
+
-Postman will prompt whether you want to open the Collection in Postman for Chrome or Postman for Windows / Mac. Select the application you have installed.
+Postman will prompt whether you want to open the Collection in Postman for Chrome or Postman for Windows/Mac. Select the application you installed.
-
+Once you make a selection, the selected Postman application will open and the collection will be imported.
-Once you have made a selection, the selected Postman application will be opened and the collection will be imported.
+Our API Collections are organized into folders that categorize the various API calls according to category. For example, you will find all the Users methods under the **Users** folder in the Management API.
-
+## Configure Postman Environment
-Our API Collections are organized into folders which categorizes the various API calls according to category, so for example, for the Management API you will find all the Users methods under the **Users** folder.
+The Auth0 Postman Collections make use of environment variables to customize the requests that are sent. To learn more about managing Postman environments, see [Setting up an environment with variables](https://learning.postman.com/docs/postman/variables-and-environments/variables/).
-## Configuring the Postman Environment
+You must create an environment and configure the following variables:
-The Auth0 Postman collections make use of environment variables to customize the requests being sent. More information on managing Postman environments can be found at [Setting up an environment with variables](https://www.getpostman.com/docs/environments)
+| Variable | Description |
+| -- | -- |
+| `auth0_domain` | Should contain the domain for your Auth0 tenant, such as `jerrie.auth0.com`. |
+| `auth0_token` | Should contain the token needed to make calls to the Management API. Is only required when using the Management API collection. To learn more, see [How to Get an Access Token for the Management API](/api/management/v2/tokens). |
-You will need to create an environment and configure the following variables:
+In the screenshot below, you can see a Postman environment configured with both the `auth0_domain` and `auth0_token` variables defined:
-* `auth0_domain`: Should contain the domain for your Auth0 tenant, such as **jerrie.auth0.com**.
-* `auth0_token`: Should contain the token needed when making calls to the Management API, and is therefore only required when using the Management API collection. More information on how to generate a token can be found at [The Auth0 Management APIv2 Token](https://auth0.com/docs/api/management/v2/tokens)
+
-In the screenshot below you can see a Postman environment configured with both the `auth0_domain` and `auth0_token` variables defined:
-
-
-
-## Executing a request
+## Execute requests
Once the environment is configured, you can follow these steps to execute an Auth0 API method:
-1. Select the environment you want to work with
-2. Select the relevant API method in the collection folder
-3. Click the send button
-
-
+1. Select the environment with which you want to work.
+2. Select the relevant API method in the collection folder.
+3. Click the **Send** button.
-You may also optionally have to configure query parameters or the JSON method body, depending on the API call. For more information please refer to the [Sending Requests](https://www.getpostman.com/docs/requests) document on the Postman website.
+
-## A word about storing tokens in Postman variables
+You may also have to configure query parameters or the JSON method body, depending on the API call. To learn more, see [Sending Requests](https://learning.getpostman.com/docs/postman/sending-api-requests/requests/).
-We do need to point out that storing tokens in Postman as environment variables could pose a potential security risk. If you are signed in to the Postman application it will automatically try and [synchronize some entities such as Collections and Environments with the Postman servers](https://www.getpostman.com/docs/sync_overview). This means that a token, which could allow someone else to gain access to your Management API, is leaving the privacy of your computer and uploaded Postman's servers.
+::: warning
+Storing tokens in Postman as environment variables could pose a security risk. If you are signed in to the Postman application, it will automatically try to [synchronize entities such as Collections and Environments with the Postman servers](https://www.getpostman.com/docs/sync_overview). This means that a token, which could allow someone else to gain access to your Management API, is leaving the privacy of your computer and being uploaded to Postman's servers.
-It also has to be said that Postman has taken measures to ensure that this information is encrypted, and indeed encourages users to store this sort of information in Environment Variables. You can [read more about this on their website](https://www.getpostman.com/docs/security).
+That said, Postman has taken measures to ensure that tokens are encrypted and encourages users to store them in Environment Variables. You can read more at [Postman Security](https://www.getpostman.com/security).
-If you feel that this still poses too much of a risk for you, then you will need to sign out of Postman to ensure that environment variables are not synchronized.
+If you feel that this still poses too much of a risk, then you will need to sign out of Postman to ensure that environment variables are not synchronized.
+:::
\ No newline at end of file
diff --git a/articles/appliance/admin/backing-up-the-appliance-instances.md b/articles/appliance/admin/backing-up-the-appliance-instances.md
index 4751b9ce8b..a8a8111de9 100644
--- a/articles/appliance/admin/backing-up-the-appliance-instances.md
+++ b/articles/appliance/admin/backing-up-the-appliance-instances.md
@@ -1,6 +1,13 @@
---
section: appliance
description: Recommendations on when to back up PSaaS Appliance instances
+topics:
+ - appliance
+ - backups
+contentType: concept
+useCase: appliance
+applianceId: appliance1
+sitemap: false
---
# PSaaS Appliance Administration: Appliance Backups
diff --git a/articles/appliance/admin/creating-tenants.md b/articles/appliance/admin/creating-tenants.md
deleted file mode 100644
index 5cccf6b44d..0000000000
--- a/articles/appliance/admin/creating-tenants.md
+++ /dev/null
@@ -1,136 +0,0 @@
----
-section: appliance
-description: How to automatically create tenants in the PSaaS Appliance
----
-
-# PSaaS Appliance Administration: Automatic Creation of Tenants
-
-If your business needs require you to create tenants regularly, you may automate this process in the PSaaS Appliance. For example, you might need to create one tenant for each customer or project that goes live.
-
-## Creating a Management API Application for the Root Tenant Authority
-
-1. Choose the Root Tenant Authority (RTA) tenant using the drop-down menu located in the top right-hand side of the Dashboard.
-2. Go to the Applications page.
-3. Create an application called 'Tenant Provisioning.'
-4. Once you have created the 'Tenant Provisioning' application, go to the Connections tab and disable **all** Connections for this application.
-5. Navigate to `${manage_url}/#/apis`. Click the link to open the Auth0 Management API.
-6. Go to the Machine to Machine Applications tab, and enable Tenant Provisioning by moving the associated slide to the right.
-7. Create the new application grant.
-
-### Creating the New Application Grant
-
-1. Navigate to the [Management API Explorer](/api/management/v2#!/Client_Grants/post_client_grants) to generate the required `POST` call.
-2. Click the bubble that says **'create:client_grants'** to select that Scope.
-3. Paste the following payload into the provided `body` box after you have supplied the client ID and the root tenant authority:
- ```text
- {
- 'client_id': '${account.clientId}',
- 'audience': 'https://ROOT_TENANT_AUTHORITY/api/v2/',
- 'scope': ['create:tenants']
- }
- ```
-4. Click 'Try' to test the provided information. If you receive a `201` response, you may proceed to click on the 'get curl command' link to generate the required `POST` call. It will contain the following information:
-
- ```har
- {
- "method": "POST",
- "url": "https://ROOT_TENANT_AUTHORITY/api/v2/client-grants",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [],
- "queryString" : [],
- "postData": {
- "mimeType": "application/json",
- "text" : "{ \"client_id\": \"${account.clientId}\", \"audience\": \"https://ROOT_TENANT_AUTHORITY/api/v2/\", \"scope\": [\"create:tenants\"] }"
- },
- "headersSize" : -1,
- "bodySize" : -1,
- "comment" : ""
- }
- ```
-
-## Using the New Application grant
-
-Once you have created your New Application Grant, you may use it to complete the following tasks.
-
-### Getting an Access Token
-
-```har
-{
- "method": "POST",
- "url": "https://ROOT_TENANT_AUTHORITY_DOMAIN/oauth/token",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [
- { "name": "cache-control", "value": "no-cache" },
- { "name": "content-type", "value": "application/json" }
- ],
- "queryString" : [],
- "postData" : {
- "mimeType": "application/json",
- "text": "{\"audience\": \"https://ROOT_TENANT_AUTHORITY/api/v2/\", \"grant_type\": \"client_credentials\",\"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\"}"
- },
- "headersSize" : -1,
- "bodySize" : -1,
- "comment" : ""
-}
-```
-
-In return, you will receive the Access Token:
-
-```text
-{
- 'access_token': 'eyJ0eXAiO...'
-}
-```
-
-### Creating a Tenant
-
-You may use the following call create a tenant. Once the tenant is created, the API responds with a Client ID and Secret that grants access to the Management API for the newly-created tenant (which you can then use to get additional Access Tokens--see the following section for the sample call).
-
-```har
-{
- "method": "POST",
- "url": "https://ROOT_TENANT_AUTHORITY_DOMAIN/api/v2/tenants",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [
- { "name": "cache-control", "value": "no-cache" },
- { "name": "content-type", "value": "application/json" },
- { "name": "authorization", "value": "Bearer ACCESS_TOKEN" }
- ],
- "queryString" : [],
- "postData" : {
- "mimeType": "application/json",
- "text": "{\"name\": \"customer-1\",\"owners\": [\"me@email.com\"]}"
- },
- "headersSize" : -1,
- "bodySize" : -1,
- "comment" : ""
-}
-```
-
-#### Getting an Access Token for the Newly-Created Tenant
-
-This snippet shows how you can get an Access Token for the newly-created tenant, which you can then use to call the Management API.
-
-```har
-{
- "method": "POST",
- "url": "https://NEW_TENANT_DOMAIN/oauth/token",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [
- { "name": "cache-control", "value": "no-cache" },
- { "name": "content-type", "value": "application/json" }
- ],
- "queryString" : [],
- "postData" : {
- "mimeType": "application/json",
- "text": "{\"audience\": \"https://NEW_TENANT_DOMAIN/api/v2/\", \"grant_type\": \"client_credentials\", \"client_id\": \"MANAGEMENT_CLIENT_ID\", \"client_secret\": \"MANAGEMENT_CLIENT_SECRET\"}"
- },
- "headersSize" : -1,
- "bodySize" : -1,
- "comment" : ""
-}
-```
diff --git a/articles/appliance/admin/disabling-sign-ups.md b/articles/appliance/admin/disabling-sign-ups.md
index 65a3152e79..219fc4f573 100644
--- a/articles/appliance/admin/disabling-sign-ups.md
+++ b/articles/appliance/admin/disabling-sign-ups.md
@@ -1,6 +1,13 @@
---
description: Auth0 suggests that you disable sign-ups for the `Initial-Connection` database connection prior to going live in your production environments.
section: appliance
+topics:
+ - appliance
+ - signups
+contentType: how-to
+useCase: appliance
+applianceId: appliance3
+sitemap: false
---
# PSaaS Appliance Administration: Disabling Sign-Ups
diff --git a/articles/appliance/admin/federated-access-to-manage.md b/articles/appliance/admin/federated-access-to-manage.md
new file mode 100644
index 0000000000..a5633b68fd
--- /dev/null
+++ b/articles/appliance/admin/federated-access-to-manage.md
@@ -0,0 +1,65 @@
+---
+description: How to set up federated login to the Manage Dashboard
+section: appliance
+topics:
+ - appliance
+ - admin
+ - signups
+contentType: how-to
+useCase: appliance
+applianceId: appliance76
+sitemap: false
+---
+# Set Up Federated Login to the Manage Dashboard
+
+If you use an Identity Provider (IdP) to handle your staff logins, you can use the IdP with your root tenant authority (otherwise known as the RTA or your config tenant) to provide federated access to your Dashboard.
+
+By using your IdP, this eliminates the need for you to:
+
+* *For customer-hosted PSaaS Appliance:* Manually create users in the root tenant authority (RTA)
+* *For Auth0-hosted PSaaS Appliance:* Open a support case requesting the addition of a Dashboard administrator.
+
+::: note
+If you have an Auth0-hosted PSaaS Appliance, but you do not have access to the root tenant, please submit a [Support Ticket](${env.DOMAIN_URL_SUPPORT}) and the Appliance Services staff will help you set this up.
+:::
+
+## Setting Up Federated Access
+
+The Auth0 root tenant acts as an identity provider (IdP) for the Manage Dashboard. As such, you will need to add a Service Provider (SP) to your existing IdP to federate access to the Manage Dashboard.
+
+This process requires the following three steps:
+
+1. Set up the Auth0 Service Provider (SP)
+ *For customers with Auth0-hosted PSaaS Appliance: Auth0 will create the Connection for you after you provide the necessary setup information.*
+2. Provide your Service Provider metadata to the Identity Provider (IdP)
+3. Test the Identity Provider
+
+Please note that how you complete the three steps above differ slightly based on whether you're working with a customer-hosted PSaaS Appliance or an Auth0-hosted PSaaS Appliance.
+
+### Customer-hosted PSaaS Appliance
+
+[Configure Auth0 as the Service Provider (SP)](/protocols/saml/saml-configuration/auth0-as-service-provider) and use both the root tenant authority and the new Service Provider Connection to access Auth0.
+
+### Auth0-hosted PSaaS Appliance
+
+[Configure Auth0 as the Service Provider (SP)](/protocols/saml/saml-configuration/auth0-as-service-provider). Follow the tutorial up through the section where you identify the Identity Provider (IdP) and Connection protocol (you will be stopping at the section where you're shown how to Configure Auth0).
+
+Please be sure to configure your mappings between Auth0 (as the SP) and your IdP in the form of Assertions. You can do so in the Dashboard by going to **Connections** > **Enterprise** > **SAMLP Identity Provider**. Find your connection, and click the cog icon to launch the **Settings** tab. Switch to the **Mappings** view, and provide mappings for **name**, the **name format** (optional), and **value**. The specifics will vary based on the IdP you're using, so please contact Auth0 if you have any questions.
+
+At this point, send Auth0 the information you've collected in a [Support Ticket](${env.DOMAIN_URL_SUPPORT}) and request that you be granted federated access to the config tenant/RTA.
+
+In your Support ticket, you should include:
+
+* The **email domain(s)** that will be redirected to your Identity Provider
+* The Identity Provider's **single sign-on URL**
+* The Identity Provider's **public key** (encoded in PEM or CER format)
+* The **sign out URL** (optional)
+
+You can find most of this information in the XML metadata file provided by your Identity Provider. If you'd prefer, you can send Auth0 this file, along with the email domains that you will be redirecting to the IdP.
+
+Once Auth0 receives all of the information we need, we will:
+
+* Create a Connection in your root tenant
+* Provide you with the metadata link containing the information you need to provide to your Identity Provider
+
+Once you provide this information (as well as the callback URL and the Entity ID) to your IdP, you will be able to test your federated Login to the Dashboard.
\ No newline at end of file
diff --git a/articles/appliance/admin/importance-of-updates.md b/articles/appliance/admin/importance-of-updates.md
new file mode 100644
index 0000000000..c38ad249b4
--- /dev/null
+++ b/articles/appliance/admin/importance-of-updates.md
@@ -0,0 +1,35 @@
+---
+section: appliance
+description: Why it is important to regularly update the PSaaS Appliance
+topics:
+ - appliance
+ - updates
+ - security
+contentType: concept
+useCase: appliance
+applianceId: appliance75
+sitemap: false
+---
+# Why You Should Update the PSaaS Appliance Regularly
+
+Though the Auth0 engineering team releases updates to the PSaaS Appliance on a monthly basis, we understand that such frequent updates to your environment (though ideal) are not always possible. Regardless, we recommend updating your PSaaS Appliance on a bi-monthly or quarterly basis at the very least.
+
+In this article, we will cover why it is essential to update your PSaaS Appliance regularly.
+
+## Benefits to updating the PSaaS Appliance
+
+First, each major release contains all of the new features and improvements to existing features that we have made since the prior version.
+
+However, even if you are happy with your existing feature set, there are also benefits to updating the PSaaS Appliance that extend beyond technological improvements and feature updates.
+
+More specifically, each major release for the PSaaS Appliance includes fixes for all of the known issues discovered during normal usage of Auth0. We aim to provide as smooth an experience as possible for all of our customers, but an issue-free release is not possible. As such, we ship updates that correct any issues that might become apparent.
+
+## Problems that may arise due to delayed or skipped updates
+
+By upgrading routinely, you can be assured that you are working with a version of the PSaaS Appliance that is fully-functional and secure. Conversely, if you do not upgrade, your environment becomes, over time, unsupported and less secure.
+
+Furthermore, lack of updates to the PSaaS Appliance over time makes it difficult when you do get to the point where you want to update. Because updates are cumulative, skipping updates means that you will have more changes that need to be tested. By updating at each possible opportunity, you are making smaller, incremental changes to your environment.
+
+## Testing in the Development Environment to ensure smooth updates
+
+Auth0 provides a Development environment at no cost to you. The purpose of this environment is to test future upgrades to identify any issues before updating your Production environment. Auth0 works with you to resolve any problems identified during your testing, and only when both parties are comfortable should the upgrade proceed to Production.
diff --git a/articles/appliance/admin/index.md b/articles/appliance/admin/index.md
index a0f776bbdf..cdde2ec3c8 100644
--- a/articles/appliance/admin/index.md
+++ b/articles/appliance/admin/index.md
@@ -3,17 +3,24 @@ url: /appliance/admin
section: appliance
description: >
This document covers factors PSaaS Appliance administrators should be aware of when working with production PSaaS Appliance.
+topics:
+ - appliance
+ - administration
+contentType: index
+useCase: appliance
+applianceId: appliance4
+sitemap: false
---
# PSaaS Appliance: Administrator's Manual
This document covers factors PSaaS Appliance administrators should be aware of when working with production PSaaS Appliance instances.
-* [Managing the Dashboard](/appliance/admin/managing-the-dashboard);
-* [Disabling Sign-ups](/appliance/admin/disabling-sign-ups);
+* [Managing the Dashboard](/appliance/admin/managing-the-dashboard)
+* [Disabling Sign-ups](/appliance/admin/disabling-sign-ups)
* [Inviting/Adding Co-Administrators](/appliance/admin/inviting-coadmins)
-* [Backing up the PSaaS Appliance](/appliance/admin/backing-up-the-appliance-instances);
-* [Monitoring & Performing Health Checks on Load Balancers](/appliance/admin/monitoring);
-* [Limiting SSH Access](/appliance/admin/limiting-ssh-access);
-* [Updating the PSaaS Appliance](/appliance/admin/updating-the-appliance);
-* [Configuring Custom Error Pages](/hosted-pages/custom-error-pages).
+* [Backing up the PSaaS Appliance](/appliance/admin/backing-up-the-appliance-instances)
+* [Monitoring & Performing Health Checks on Load Balancers](/appliance/admin/monitoring)
+* [Updating the PSaaS Appliance](/appliance/admin/updating-the-appliance)
+ * [Why You Should Update the PSaaS Appliance Regularly](/appliance/admin/importance-of-updates)
+* [Configuring Custom Error Pages](/universal-login/custom-error-pages)
diff --git a/articles/appliance/admin/inviting-coadmins.md b/articles/appliance/admin/inviting-coadmins.md
index 59026f316a..a5f17a2222 100644
--- a/articles/appliance/admin/inviting-coadmins.md
+++ b/articles/appliance/admin/inviting-coadmins.md
@@ -1,6 +1,13 @@
---
section: appliance
description: How to invite additional administrators to your PSaaS Appliance
+topics:
+ - appliance
+ - coadmins
+contentType: how-to
+useCase: appliance
+applianceId: appliance5
+sitemap: false
---
# PSaaS Appliance Administration: Inviting Co-Administrators
diff --git a/articles/appliance/admin/limiting-ssh-access.md b/articles/appliance/admin/limiting-ssh-access.md
index e6645eb3bb..4d0b93b513 100644
--- a/articles/appliance/admin/limiting-ssh-access.md
+++ b/articles/appliance/admin/limiting-ssh-access.md
@@ -1,10 +1,18 @@
---
section: appliance
description: When and why you should grant SSH access to the PSaaS Appliance
+topics:
+ - appliance
+ - ssh
+ - security
+contentType: concept
+useCase: appliance
+applianceId: appliance6
+sitemap: false
---
# PSaaS Appliance Administration: Limiting SSH Access
Auth0 requires SSH access in order to connect to the PSaaS Appliance to perform updates or troubleshooting/accessing required logs. These are the only instances where SSH (by default, port 22) should be exposed on the nodes.
-In all other instances, Auth0 recommends restricting SSH access to the PSaaS Appliance. For Appliance deployments in the cloud, you would *not* enable the SSH endpoint for your virtual machines. For on-premise PSaaS Appliance deployments, you would deny SSH to to the virtual machines in your corporate firewall.
+In all other instances, Auth0 recommends restricting SSH access to the PSaaS Appliance. For Appliance deployments in the cloud, you would *not* enable the SSH endpoint for your virtual machines. For on-premise PSaaS Appliance deployments, you would deny SSH to the virtual machines in your corporate firewall.
diff --git a/articles/appliance/admin/managing-the-dashboard.md b/articles/appliance/admin/managing-the-dashboard.md
index 83ca580c8a..5ad7477bc3 100644
--- a/articles/appliance/admin/managing-the-dashboard.md
+++ b/articles/appliance/admin/managing-the-dashboard.md
@@ -1,6 +1,13 @@
---
section: appliance
description: How to access and restrict access to the PSaaS Appliance Management Dashboard
+topics:
+ - appliance
+ - dashboard
+contentType: how-to
+useCase: appliance
+applianceId: appliance7
+sitemap: false
---
# PSaaS Appliance Administration: Manage the Dashboard
diff --git a/articles/appliance/admin/monitoring.md b/articles/appliance/admin/monitoring.md
index 2cbc24e5c6..751be898b9 100644
--- a/articles/appliance/admin/monitoring.md
+++ b/articles/appliance/admin/monitoring.md
@@ -1,6 +1,13 @@
---
section: appliance
description: How to monitor the PSaaS Appliance
+topics:
+ - appliance
+ - monitoring
+contentType: how-to
+useCase: appliance
+applianceId: appliance8
+sitemap: false
---
# PSaaS Appliance Administration: Monitoring
diff --git a/articles/appliance/admin/rate-limiting.md b/articles/appliance/admin/rate-limiting.md
index 1e0145f58e..5e276a2e64 100644
--- a/articles/appliance/admin/rate-limiting.md
+++ b/articles/appliance/admin/rate-limiting.md
@@ -1,10 +1,17 @@
---
title: Rate Limiting in the PSaaS Appliance
description: How to enable, configure, and test for rate limiting in the Appliance
+topics:
+ - appliance
+ - rate-limiting
+contentType: how-to
+useCase: appliance
+applianceId: appliance9
+sitemap: false
---
# PSaaS Appliance: Rate Limiting
-Beginning with PSaaS Appliance build `6576`, rate limits for API endpoints can be enabled and configured in the Dashboard. Rate limiting in the PSaaS Appliance is done using [limitd](https://github.com/limitd/limitd#buckets).
+Rate limits for API endpoints can be enabled and configured in the Dashboard. Rate limiting in the PSaaS Appliance is done using [limitd](https://github.com/limitd/limitd#buckets).
## Enable and Configure Rate Limiting
@@ -64,4 +71,4 @@ Strict-Transport-Security: max-age=15724800
X-Robots-Tag: noindex, nofollow, nosnippet, noarchive
[{"id":"con_sw...O","options":{"mfa":{"active":true,"return_enroll_settings":true},"disable_signup":true,"brute_force_protection":true,"strategy_version":2},"strategy":"auth0","name":"Initial-Connection","enabled_clients":["aCb...C","ef7...Z"],"is_domain_connection":false,"realms":["Initial-Connection"]}]
-```
\ No newline at end of file
+```
diff --git a/articles/appliance/admin/updating-the-appliance.md b/articles/appliance/admin/updating-the-appliance.md
index 5c58bf8839..bfec4751aa 100644
--- a/articles/appliance/admin/updating-the-appliance.md
+++ b/articles/appliance/admin/updating-the-appliance.md
@@ -1,36 +1,82 @@
---
section: appliance
description: How to update the PSaaS Appliance
+toc: true
+topics:
+ - appliance
+ - updates
+contentType: how-to
+useCase: appliance
+applianceId: appliance10
+sitemap: false
---
-
# Updating the PSaaS Appliance
-To ensure that your PSaaS Appliance has the latest functionality, security, and bug fixes, Auth0 requires you to perform regular updates. While the Auth0 engineering team releases updates on a monthly basis, you should plan updates on a monthly, bi-monthly, and quarterly basis. You should not exceed **90 days** without updating the PSaaS Appliance.
+To [ensure that your PSaaS Appliance has the latest functionality, security, and bug fixes](/appliance/admin/importance-of-updates), Auth0 requires you to perform regular updates. While the Auth0 engineering team releases updates on a monthly basis, you should plan updates on a monthly, bi-monthly, and quarterly basis.
+
+Appliances must be updated using a **major release** at least once every **90 days**.
+
+## Releases
-::: note
For more information about PSaaS Appliance Releases, please see the [Change Log](https://auth0.com/changelog/appliance).
-:::
-## Best Practices
+## Types of updates
+
+There are two types of updates: **major** and **minor** releases.
+
+### Major releases
+
+**Major releases** can be identified by changes in the PSaaS Appliance version number (i.e. from **14591.X** to **15838.X**). These updates include new features and/or changes in existing functionality.
+
+### Minor releases
+
+**Minor releases** (or patch releases) can be identified by changes in the *decimal* value of the version number (i.e. **15838.35** is a minor update to **15838.31**).
+
+Patches are cumulative; that is, patch **15838.85** includes changes included in all prior patches (**15838.75**, **15838.43**, **15838.36**, **15838.35**, and **15838.31**).
+
+You do *not* need to install all released patches, but we recommend doing so since patches typically include things like bug and security fixes.
+
+## The update process
+
+The update process will vary slightly depending on whether you have an **Auth0-hosted PSaaS Appliance** or a **self-hosted PSaaS Appliance**.
+
+### Auth0-hosted PSaaS Appliance
+
+When you are ready to update, submit a Support ticket indicating:
+
+* That you are ready to update your Development environment
+* When you would like Auth0 to perform the upgrade
+* What version you would like to upgrade to
+
+We will contact you to determine the specific time frame during which the update occurs.
+
+Once we have updated your Development environment, we recommend you spend one week testing. If, at that point, everything is working, we will schedule a time frame for updates to the Production environment(s).
+
+### Self-hosted PSaaS Appliance
+
+You can apply **minor** updates without coordination with Auth0. However, we recommend updating your Development nodes and testing prior to applying the changes to your Production environment.
+
+For **major** updates, please submit a Support ticket and Auth0 will reach out to confirm if manual intervention on the part of Auth0 is required.
To ensure the update process goes as smoothly as possible, we recommend following the best practices detailed below.
-### Prior to the Update
+#### Prior to the Update
* Take a VM snapshot of each node you're updating.
* Ensure that you've enabled access to your nodes for the Auth0 Customer Success Engineer who will be assisting you with the update.
* Complete the pre-check test **one hour** prior the start of the update.
* Please be sure that your infrastructure engineer has administrative access to the Dashboard (specifically the Root Tenant Authority).
* Ensure that all [Health Checks](/appliance/dashboard/troubleshoot#health-check) are okay.
+* For multi-node clusters, check the **Enable Sequential Updates** box if you want to reduce downtime during the update.
::: note
For additional information on gathering testing information, please see [PSaaS Appliance Monitoring](/appliance/monitoring).
:::
* Update the Development/Test environment prior to upgrading Production. This allows you to test the new version to identify any issues before you apply it to Production. We recommend performing this test for a one-week period.
-* Ensure that the PSaaS Appliance is able to access the internet during the update process, as well as the outbound IP addresses listed in the ["Updates" column](/appliance/infrastructure/ip-domain-port-list#external-connectivity). The update is [trigged via the Management Dashboard](/appliance/dashboard/updates) and requires the downloading of the application itself, as well as any operating system updates. The update takes between 60 minutes (for a single Development node) to 90 minutes (for a three-node Production cluster).
+* Ensure that the PSaaS Appliance is able to access the internet during the update process, as well as the outbound IP addresses listed in the ["Updates" column](/appliance/infrastructure/ip-domain-port-list#external-connectivity). The update is [triggered via the Management Dashboard](/appliance/dashboard/updates) and requires the downloading of the application itself, as well as any operating system updates.
-### After the Update
+#### After the update
::: note
For additional information on gathering testing information, please see [PSaaS Appliance Monitoring](/appliance/monitoring).
@@ -39,20 +85,35 @@ For additional information on gathering testing information, please see [PSaaS A
* Perform the post-test check:
* Check to see if all instances list the same update count and that they're currently running the latest version.
* Check that all Health Checks are okay.
- * Run smoke tests to ensure that there are no issues with the update.
-Please remember that you are responsible for testing and ensuring that all of your applications work as expected.
+* Run smoke tests to ensure that there are no issues with the update.
-## Coordination with Auth0
+ The specifics of what constitutes a complete smoke check for your PSaaS Appliance varies, since the appropriate tests vary based on your implementation and usage of Auth0. Furthermore, each organization prefers different levels of detail when it comes to testing -- some prefer more thorough testing than others. Regardless, we recommend testing at the very least:
-While most updates require manual installation of patches by an Auth0 Customer Success Engineering, some updates are self-service and can be performed using the [Updates page](/appliance/dashboard/updates).
+ 1. All application functionality that involves authentication flows or user identity changes
+ 2. Basic access to the Auth0 Management Dashboard
-We recommend that you let Auth0 known when you plan on upgrading your Development node.
+ Some of the areas and processes that you might consider including in your smoke tests include:
-Production upgrades should **always** be performed in conjunction with an Auth0 Customer Success Engineer. We will schedule these updates so that an Auth0 Customer Success Engineer is on the call with your operations team during the entire process.
+ * Registration
+ * Login (including those involving Social or other identity providers)
+ * Logout
+ * Password reset
+ * Single sign-on (SSO)
+ * Passwordless/SMS login
+ * User metadata updates
+ * Machine-to-machine interactions
+ * SDK usage
+ * Mobile and desktop usage
+ * Login and use of the Auth0 Management Dashboard
+ * Extensions (make sure that the ones you've installed are functioning as expected
+
+Please remember that you are responsible for testing and ensuring that all of your applications work as expected.
## Downtime
-During an upgrade, we expect there to be 3-5 minute window of downtime. This occurs when we restart services. Because of this, we are willing to schedule updates to Production clusters during non-business hours. Please contact your Customer Success Manager to select a time that would be best for you.
+During an upgrade, we expect there to be some downtime. For single-node clusters, we expect there to be 3-5 minutes of downtime. For multi-node clusters, we can perform updates sequentially, where users may see up to 30 seconds of downtime.
+
+Downtime occurs when we restart services. Because of this, we are willing to schedule updates to Production clusters during non-business hours. Please let us know your preferences in the Support Ticket.
If you require your Production update during non-business hours, we ask that you confirm the day prior during normal business hours.
diff --git a/articles/appliance/appliance-overview.md b/articles/appliance/appliance-overview.md
index f501e1a7f1..ed9bfb70b7 100644
--- a/articles/appliance/appliance-overview.md
+++ b/articles/appliance/appliance-overview.md
@@ -1,6 +1,12 @@
---
section: appliance
description: The PSaaS Appliance is an option for your organization when compliance or other policy requirements prevent you from using a multi-tenant cloud service.
+topics:
+ - appliance
+contentType: concept
+useCase: appliance
+applianceId: appliance52
+sitemap: false
---
# PSaaS Appliance Overview
@@ -8,12 +14,7 @@ description: The PSaaS Appliance is an option for your organization when complia
The PSaaS Appliance is an option for your organization when compliance or other policy requirements prevent you from using a multi-tenant cloud service. The PSaaS Appliance can be deployed in one of three places:
* a dedicated cloud environment hosted by Auth0 (you may opt for a shared cloud environment or an environment where resources are allocated only to your company).
-* your cloud environment using **Amazon AWS** or **Microsoft Azure**. Other public cloud service providers will need to be reviewed.
-* your own datacenter (as a managed service) using **VMWare** or **Microsoft Hyper-V**.
-
-::: note
-Please contact us for additional information if you are interested in using cloud environments and/or virtualization environments not listed above.
-:::
+* your cloud environment using **Amazon AWS**
## Infrastructure
@@ -74,7 +75,7 @@ If Auth0 is managing a dedicated environment for you, Auth0 will obtain your con
### Connectivity
-During maintenance operations, the PSaaS Appliance instances contact external Auth0 endpoints for updating under your consent and supervision. After maintenance completes, you can block Internet access to the PSaaS Appliance.
+During maintenance operations, the PSaaS Appliance instances contact external Auth0 endpoints for updating under your consent and supervision. After maintenance completes, you can [continue to operate with limited internet access](/appliance/infrastructure/internet-restricted-deployment).
For normal maintenance, Auth0 will access the Management Dashboard (either over a temporary SSH connection or through remote control software) to apply the update. Auth0 will also need SSH access in the event that updates to the PSaaS Appliance are necessary. If you expose API endpoints to be used for monitoring, Auth0 will collect this information to proactively monitor PSaaS Appliance behavior for you.
diff --git a/articles/appliance/cli/adding-node-to-backup-role.md b/articles/appliance/cli/adding-node-to-backup-role.md
index 14d254a6c0..fad2cdabe9 100644
--- a/articles/appliance/cli/adding-node-to-backup-role.md
+++ b/articles/appliance/cli/adding-node-to-backup-role.md
@@ -1,14 +1,19 @@
---
section: appliance
description: How to add an PSaaS Appliance node in the backup node
+topics:
+ - appliance
+ - backups
+ - cli
+ - nodes
+contentType: how-to
+useCase: appliance
+applianceId: appliance11
+sitemap: false
---
# PSaaS Appliance: Adding a Node to the Backup Role
-::: note
- This document applies beginning with PSaaS Appliance update **build 7247**.
-:::
-
## Prerequisites
* Backup can be configured on single or multiple-node setups. In multi-node setups, the backup must be placed on a non-primary device.
diff --git a/articles/appliance/cli/backing-up-the-appliance.md b/articles/appliance/cli/backing-up-the-appliance.md
index 0f9530d7b8..f382361fb5 100644
--- a/articles/appliance/cli/backing-up-the-appliance.md
+++ b/articles/appliance/cli/backing-up-the-appliance.md
@@ -2,6 +2,14 @@
section: appliance
description: How to back up the PSaaS Appliance using its CLI
toc: true
+topics:
+ - appliance
+ - cli
+ - backups
+contentType: how-to
+useCase: appliance
+applianceId: appliance12
+sitemap: false
---
# How to Back Up the PSaaS Appliance Using the CLI
@@ -24,7 +32,7 @@ Please be aware that we use the following sample values throughout this document
* IP address of the node on the replica set to be backed up: `192.168.1.186`. Generically, the node may also be referred to as ``.
* Password used for encryption: `Passw0rd`.
-* The replica set connection string: `a0/a0-1:27017,a0-2:27017,a0-3:27017`
+* The replica set connection string: `a0/a0-1:27017,a0-2:27017,a0-3:27017`.
## Generate a New Backup
@@ -58,10 +66,10 @@ To do this, you can use the `backup-sensitive` command, which works the same way
The full instructions (along with the commands you'll need to run) are as follows:
-1. Request a backup: `a0cli -t node_IP_address backup-sensitive --password 0therPassw0rd`
-2. Check the status of a backup: `a0cli -t node_IP_address backup-sensitive-status`
-3. Retrieve backup of sensitive information: `a0cli -t node_IP_address backup-sensitive-retrieve`
-4. Delete the sensitive backup from the node: `a0cli -t node_IP_address backup-sensitive-delete`
+1. Request a backup: `a0cli -t node_IP_address backup-sensitive --password 0therPassw0rd`;
+2. Check the status of a backup: `a0cli -t node_IP_address backup-sensitive-status`;
+3. Retrieve backup of sensitive information: `a0cli -t node_IP_address backup-sensitive-retrieve`;
+4. Delete the sensitive backup from the node: `a0cli -t node_IP_address backup-sensitive-delete`.
## Check the Status of the Backup
diff --git a/articles/appliance/cli/configure-cli.md b/articles/appliance/cli/configure-cli.md
index c4d4f91c64..90b57df34f 100644
--- a/articles/appliance/cli/configure-cli.md
+++ b/articles/appliance/cli/configure-cli.md
@@ -1,6 +1,13 @@
---
section: appliance
description: How to configure the PSaaS Appliance CLI
+topics:
+ - appliance
+ - cli
+contentType: how-to
+useCase: appliance
+applianceId: appliance13
+sitemap: false
---
# Configuring and Using the Auth0 Appliance Command Line Interface
@@ -9,7 +16,7 @@ The PSaaS Appliance Command Line Interface (CLI) allows you to perform operation
## Downloading the CLI Setup Files
-To download the files required to set up the CLI, please contact your Auth0 Customer Success Manager for your custom download link.
+To download the files required to set up the CLI, submit a [support ticket](https://support.auth0.com/tickets) for your custom download link.
## Installing and Using the CLI
@@ -26,7 +33,7 @@ Usage: a0cli [options]
create-key Creates private/public keys pair on current path.
show-key Shows public key on current path.
delete-key Deletes keys pair from current path.
- update-commands Retrieve availables commands from the specified node.
+ update-commands Retrieve available commands from the specified node.
Options:
@@ -47,7 +54,7 @@ Usage: a0cli [options]
create-key Creates private/public keys pair on current path.
show-key Shows public key on current path.
delete-key Deletes keys pair from current path.
- update-commands Retrieve availables commands from the specified node.
+ update-commands Retrieve available commands from the specified node.
backup Creates a new backup.
backup-delete Deletes the current sensitive backup
backup-retrieve retrieves the current backup.
diff --git a/articles/appliance/cli/index.md b/articles/appliance/cli/index.md
index 16f63b5d72..8f2d5a346f 100644
--- a/articles/appliance/cli/index.md
+++ b/articles/appliance/cli/index.md
@@ -2,6 +2,14 @@
url: /appliance/cli
section: appliance
description: How to use the PSaaS Appliance CLI
+topics:
+ - appliance
+ - cli
+ - backups
+contentType: how-to
+useCase: appliance
+applianceId: appliance14
+sitemap: false
---
# Private SaaS (PSaaS) Appliance Command Line Interface
diff --git a/articles/appliance/cli/reconfiguring-ip.md b/articles/appliance/cli/reconfiguring-ip.md
index 70b05d8963..8ec85afb75 100644
--- a/articles/appliance/cli/reconfiguring-ip.md
+++ b/articles/appliance/cli/reconfiguring-ip.md
@@ -1,70 +1,18 @@
---
section: appliance
-description: How to reconfigure AppliPSaaS Applianceance IP Addresses using the CLI
+description: How to reconfigure PSaaS Appliance IP Addresses using the CLI
+topics:
+ - appliance
+ - cli
+ - ip-addresses
+contentType: how-to
+useCase: appliance
+applianceId: appliance15
+sitemap: false
---
# How to Reconfigure IP Addresses Using the Command Line Interface
-When running in a cluster, the PSaaS Appliance nodes need to know the IP addresses of the other nodes within the same cluster (they do not automatically detect each other). Whenever you move the network of the cluster, you may change the individual IP addresses using the console (TTY1) interface in the Virtual Machine Manager. However, there is no easy way to tell the cluster nodes the new IP addresses of the other members of the cluster.
+When running in a cluster, the PSaaS Appliance nodes need to know the IP addresses of the other nodes within the same cluster (they do not automatically detect each other). Whenever you move the network of the cluster, the IP addresses of the individual nodes need to be re-set to match the original node names.
-Beginning with PSaaS Appliance build **6576**, you may reconfigure the mapping of IP addresses to the names of nodes for each PSaaS Appliance node using the PSaaS Appliance's Command Line Interface (CLI). Once this is done, the nodes may resume communication with one another within that cluster.
-
-## Prerequisites
-
-Prior to beginning, please be sure to [configure the CLI](/appliance/cli/configure-cli) for use in performing operations on your PSaaS Appliance instances via authorized workstations.
-
-## Using the `re-ip` Task
-
-The `reip` task has the following signature:
-
-```text
-$a0cli -t re-ip ":[,:...]"
-```
-
-Running the above will modify the ``'s `/etc/hosts` file to point each `` to its corresponding ``.
-
-### Use Example
-
-Suppose that you run the following command:
-
-```text
-$a0cli -t 10.0.0.11 re-ip "a0-1:10.0.0.21,a0-2:10.0.0.22,a0-3:10.0.0.23"
-```
-
-Suppose that this node has the following `/etc/hosts` file:
-
-```text
-# The following lines are desirable for IPv6 capable hosts
-::1 ip6-localhost ip6-loopback
-fe00::0 ip6-localnet
-ff00::0 ip6-mcastprefix
-ff02::1 ip6-allnodes
-ff02::2 ip6-allrouters
-ff02::3 ip6-allhosts
-127.0.0.1 login.myauth0.com
-127.0.0.1 login0.myauth0.com
-127.0.0.1 login.appliancelab.net
-127.0.0.1 auth.appliancelab.net
-10.0.1.11 a0-1
-10.0.1.12 a0-2
-10.0.1.13 a0-3
-```
-
-Running the command results in the CLI modifying the `/etc/hosts` file so that it becomes the following:
-
-```text
-# The following lines are desirable for IPv6 capable hosts
-::1 ip6-localhost ip6-loopback
-fe00::0 ip6-localnet
-ff00::0 ip6-mcastprefix
-ff02::1 ip6-allnodes
-ff02::2 ip6-allrouters
-ff02::3 ip6-allhosts
-127.0.0.1 login.myauth0.com
-127.0.0.1 login0.myauth0.com
-127.0.0.1 login.appliancelab.net
-127.0.0.1 auth.appliancelab.net
-10.0.1.21 a0-1
-10.0.1.22 a0-2
-10.0.1.23 a0-3
-```
+Beginning with PSaaS Appliance build **14591**, reconfiguring of IP addresses using the PSaaS Appliance's Command Line Interface (CLI) is no longer possible. Please open a support ticket when you're ready to reconfigure your VMs' IP addresses, as this operation will be carried out by an Auth0 MSE.
diff --git a/articles/appliance/clock.md b/articles/appliance/clock.md
index d9fadd0b66..5674a7c5b0 100644
--- a/articles/appliance/clock.md
+++ b/articles/appliance/clock.md
@@ -1,12 +1,19 @@
---
section: appliance
description: How to manage the time on PSaaS Appliance
+topics:
+ - appliance
+ - time-sync
+contentType: how-to
+useCase: appliance
+applianceId: appliance53
+sitemap: false
---
# Time Synchronization
Auth0 uses several cryptographic functions that depend on the system clock.
-If you are running Auth0 on an IaaS (Infrastracture as a Service) provider (such as AWS, Microsoft Azure, and so on), time synchronization is managed automatically and you can skip these instructions.
+If you are running Auth0 on an IaaS (Infrastructure as a Service) provider (such as AWS, Microsoft Azure, and so on), time synchronization is managed automatically and you can skip these instructions.
If you are running Auth0 on your own hardware or a VM host, the PSaaS Appliance must have NTP configured correctly. In most cases, the NTP server is your Domain Controller. Contact your IT administrator for details.
diff --git a/articles/appliance/critical-issue.md b/articles/appliance/critical-issue.md
index faac684045..d7b7d47801 100644
--- a/articles/appliance/critical-issue.md
+++ b/articles/appliance/critical-issue.md
@@ -2,11 +2,20 @@
sitemap: false
section: appliance
description: Outlines additional support procedure information for enterprise subscription customers with an Auth0 PSaaS Appliance.
+topics:
+ - appliance
+ - support
+contentType:
+ - how-to
+ - concept
+useCase: appliance
+applianceId: appliance54
+sitemap: false
---
# Critical Support Issue Guidance for Appliance Customers
-This document outlines additional support procedure information for enterprise subscription customers with an PSaaS Appliance and shoud be read in conjunction with the general [Enterprise Support Guidance document](/onboarding/enterprise-support).
+This document outlines additional support procedure information for enterprise subscription customers with an PSaaS Appliance and should be read in conjunction with the general [Enterprise Support Guidance document](/onboarding/enterprise-support).
PSaaS Appliance customers must have [Enterprise Support](/onboarding/enterprise-support#premium-enterprise-support) as a minimum. Refer to your subscription agreement to confirm if other custom support or SLA coverage has been included.
@@ -20,12 +29,16 @@ A Critical Issue is defined as an Auth0 issue severely impacting your live or in
- the majority of users are adversely impacted;
- there is no workaround
+::: note
+Please do *not* submit an Urgent ticket for non-production environments. Urgent (critical) tickets are reserved for production environments.
+:::
+
## Special procedures for critical issues impacting production applications for PSaaS Appliance customers
PSaaS Appliance customers should use the [Auth0 Support Center](${env.DOMAIN_URL_SUPPORT}) as a primary method of logging a critical support issue. As part of the onboarding procedure a cloud account should be created that gives administrators the possibility to log in to Support Center and create new tickets. Set the ticket severity to **Urgent** if you need an immediate response.
::: note
-Using Support Center requires a cloud account setup. If you are unsure about this, please try logging in at the [Auth0 Support Center](${env.DOMAIN_URL_SUPPORT}) or check with your Auth0 Customer Success Manager.
+Using Support Center requires a cloud account setup. If you are unsure about this, please try logging in at the [Auth0 Support Center](${env.DOMAIN_URL_SUPPORT}) or check with your Auth0 Technical Account Manager.
:::
As a secondary point of escalation, PSaaS Appliance customers can also send an email to `productionoutage@auth0.com` to log a critical support issue. *Note that this should only be a secondary escalation point, as a ticket created in Support Center provides a more reliable way to identify the customer having the problem and interact with the user.*
@@ -33,16 +46,15 @@ As a secondary point of escalation, PSaaS Appliance customers can also send an e
### To log a critical support issue in Support Center
1. Go to the [Auth0 Support Center](${env.DOMAIN_URL_SUPPORT}) and log in with your credentials.
-2. Click on the [New Ticket](${env.DOMAIN_URL_SUPPORT}/tickets/new) button.
-3. Select the affected service. **Note that even if you only see your cloud account, you will be getting support for your PSaaS Appliance installation.**
-4. In **Environment** indicate the specific installation having the problem (such as Production, QA).
-5. For **What can we help you with?** select `Auth0 Service Issue`.
-6. For **Severity** select `Urgent`
+2. Click on the [Open Ticket](${env.DOMAIN_URL_SUPPORT}/tickets/new) button.
+3. Select your **Associated Support Cloud Tenant**, **Affected Root Tenant Authority** (optional), and **Affected Tenant** (optional).
+4. For **What can we help you with?** select **Appliance Support Incident**.
+5. For **Severity** select **Urgent**.
::: note
- If you don't select `Urgent`, the issue will not be treated as critical. You will not be able to change the severity of the ticket once it is created so if, for example, you set Severity to `High` but later realize that the situation is critical, you need to create a new ticket with `Severity` set to Urgent.
+ If you don't select **Urgent**, the issue will not be treated as critical. You will not be able to change the severity of the ticket once it is created so if, for example, you set Severity to `High` but later realize that the situation is critical, you need to create a new ticket with `Severity` set to Urgent.
:::
-7. Complete an appropriate **Subject** title.
-8. Describe the problem as completely as possible. *The more information you can provide about the issue you are having, the better we can provide quick and valuable support.*
+6. Provide an appropriate **Subject** title.
+7. Describe the problem as completely as possible. *The more information you can provide about the issue you are having, the better we can provide quick and valuable support.*
### Information to provide when logging an issue by email
@@ -55,7 +67,7 @@ To speed resolution, please provide the following when logging an issue via emai
When an issue has been logged correctly:
-* it will be acknowledged immediately by email and assigned a ticket ID number. Additional information may be requested.
+* It will be acknowledged immediately by email and assigned a ticket ID number. Additional information may be requested.
* A responding Auth0 support staff member may contact you via email and/or direct you to join a private Slack channel and/or a Zoom web conference to facilitate faster communications. However, it’s important to remember you should not initiate requests for help via a Slack channel - only via the methods outlined above. Slack channels may not be actively monitored.
* In addition to communications over a web conference or Slack, to preserve a record of an issue, any critical information, such as log files, symptoms, and so on should be sent as updates to the ticket via support center. Any conclusions or next steps should be added to the ticket as well.
* Upon resolution of the issue, an Auth0 support staff member will ask the customer for confirmation the issue has been resolved to their satisfaction and the ticket will be closed only when customer has responded and confirmed issue is resolved.
diff --git a/articles/appliance/custom-domains/index.md b/articles/appliance/custom-domains/index.md
index d2d6912613..cb3728aba9 100644
--- a/articles/appliance/custom-domains/index.md
+++ b/articles/appliance/custom-domains/index.md
@@ -2,13 +2,25 @@
url: /appliance/custom-domains
section: appliance
description: How to set up custom domains for your PSaaS Appliance
+topics:
+ - appliance
+ - custom-domains
+contentType:
+ - index
+useCase: appliance
+applianceId: appliance16
+sitemap: false
---
# Private SaaS (PSaaS) Appliance: Custom Domains
+::: warning
+Private SaaS Deployments (beginning with release 1905) must use the Auth0 [Custom Domains](/custom-domains) feature instead of the PSaas Custom Domains feature when creating new Custom Domains (regardless of whether they have existing Custom Domains using the PSaaS Custom Domains feature or not). **The PSaaS Custom Domains feature is deprecated.** Please contact your Auth0 MSE if you have any questions.
+:::
+
If you are using **PSaaS Appliance Build 5XXX** or later, you may configure custom domains using the Management Dashboard.
-Custom domains allow you to expose one or more arbitrary DNS names for a tenant. Conventionally, the PSaaS Appliance uses a three-part domain name for access, and it is the first portion of the domain name that varies depending on the tenant.
+Custom domains allow you to expose one arbitrary DNS name for a tenant. Conventionally, the PSaaS Appliance uses a three-part domain name for access, and it is the first portion of the domain name that varies depending on the tenant.
The root tenant authority (RTA) is a special domain that is configured when the PSaaS Appliance cluster(s) are first set up. It is a privileged tenant from which certain manage operations for the cluster are available. The RTA is sometimes called the configuration domain, and all users that have access to the Management Dashboard belong to an application in the RTA.
diff --git a/articles/appliance/dashboard/activity.md b/articles/appliance/dashboard/activity.md
index 15872885f7..d73389b069 100644
--- a/articles/appliance/dashboard/activity.md
+++ b/articles/appliance/dashboard/activity.md
@@ -1,12 +1,19 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard Activity page
+topics:
+ - appliance
+ - dashboard
+contentType: concept
+useCase: appliance
+applianceId: appliance17
+sitemap: false
---
# PSaaS Appliance Dashboard: Activity
::: note
- For additional information on navigating to and using the PSaaS Appliance Dashboard, please see the section on [PSaaS Appliance Controls](/appliance/dashboard#appliance-controls).
+For additional information on navigating to and using the PSaaS Appliance Dashboard, please see the section on [PSaaS Appliance Controls](/appliance/dashboard#psaas-appliance-controls).
:::
After you begin an update or make a change to the configuration, Auth0 displays progress and logs for those actions on this page in case you need the information for troubleshooting purposes.
diff --git a/articles/appliance/dashboard/cli.md b/articles/appliance/dashboard/cli.md
index b16a0d041b..f817659fb8 100644
--- a/articles/appliance/dashboard/cli.md
+++ b/articles/appliance/dashboard/cli.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard CLI page
+topics:
+ - appliance
+ - dashboard
+ - cli
+contentType: concept
+useCase: appliance
+applianceId: appliance18
+sitemap: false
---
# PSaaS Appliance Dashboard: CLI
@@ -13,7 +21,7 @@ If your PSaaS Appliance instances requires integration with the PSaaS Appliance

-Please see your vender for instructions on generating the public access keys. Once you are in possession of the required key(s), you may associate them with your PSaaS Appliance instance by clicking on "Add Key". You will then be asked for the following pieces of information:
+Please see your vendor for instructions on generating the public access keys. Once you are in possession of the required key(s), you may associate them with your PSaaS Appliance instance by clicking on "Add Key". You will then be asked for the following pieces of information:
* **Name**: the name that identifies your key;
* **Key**: the public key string.
diff --git a/articles/appliance/dashboard/index.md b/articles/appliance/dashboard/index.md
index a145e960bd..e77472478b 100644
--- a/articles/appliance/dashboard/index.md
+++ b/articles/appliance/dashboard/index.md
@@ -3,6 +3,15 @@ section: appliance
description: >
Learn how to use the Management Dashboard to configure things like your Applications, Connections, Users, and Rules.
url: /appliance/dashboard
+topics:
+ - appliance
+ - dashboard
+contentType:
+ - reference
+ - concept
+useCase: appliance
+applianceId: appliance19
+sitemap: false
---
# Private SaaS (PSaaS) Appliance Management Dashboard
@@ -31,8 +40,6 @@ For additional information about the pages contained in the PSaaS Appliance conf
[Activity](/appliance/dashboard/activity)
-[Instrumentation](/appliance/dashboard/instrumentation)
-
[Rate Limiting](/appliance/dashboard/rate-limiting)
[CLI](/appliance/dashboard/cli)
diff --git a/articles/appliance/dashboard/instrumentation.md b/articles/appliance/dashboard/instrumentation.md
deleted file mode 100644
index bb9870725b..0000000000
--- a/articles/appliance/dashboard/instrumentation.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-section: appliance
-description: Overview on instrumentation in the PSaaS Appliance
----
-
-# PSaaS Appliance Dashboard: Instrumentation
-
-The PSaaS Appliance ships with a feature called [Instrumentation](/appliance/instrumentation), which makes it easy for your PSaaS Appliance administrators or Auth0 Customer Success Engineers to gather information about the current (or previous) state of the PSaaS Appliance.
-
-If you have chosen to enable Instrumentation, you can see specific Grafana dashboards in the [PSaaS Appliance Dashboard](${manage_url}/configuration#/instrumentation).
-
-## The Instrumentation Page
-
-If you've never used the PSaaS Appliance Dashboard to view your Grafana data, you'll be asked to sign in to your Grafana account. Without these permissions, Auth0 cannot return and display your data and dashboards.
-
-
-
-Once you've logged in, you'll be able to see your data. You can set the following options to change the data displayed:
-
-* **Nodes**: The PSaaS Appliance node for which you want to view data. Each node ships with its own Grafana instance;
-* **Dashboard**: The [Grafana dashboard](http://docs.grafana.org/guides/getting_started/#dashboards-panels-rows-the-building-blocks-of-grafana) you want to see for the node you've selected;
-* **Range**: The time period for which you want data. Choose from one of the following:
-
- * Last minute;
- * Last 5 minutes;
- * Last 15 minutes;
- * Last 30 minutes;
- * Last hour.
-
-
diff --git a/articles/appliance/dashboard/nodes.md b/articles/appliance/dashboard/nodes.md
index c92688df8d..f406e27741 100644
--- a/articles/appliance/dashboard/nodes.md
+++ b/articles/appliance/dashboard/nodes.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard Nodes page
+topics:
+ - appliance
+ - dashboard
+ - nodes
+contentType: concept
+useCase: appliance
+applianceId: appliance21
+sitemap: false
---
# Auth0 Appliance Dashboard: Nodes
diff --git a/articles/appliance/dashboard/oss-components.md b/articles/appliance/dashboard/oss-components.md
index 7d1041d859..76c680a20e 100644
--- a/articles/appliance/dashboard/oss-components.md
+++ b/articles/appliance/dashboard/oss-components.md
@@ -1,7 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard OSS Components page
-
+topics:
+ - appliance
+ - dashboard
+ - oss
+contentType: concept
+useCase: appliance
+applianceId: appliance22
+sitemap: false
---
# OSS Components
diff --git a/articles/appliance/dashboard/rate-limiting.md b/articles/appliance/dashboard/rate-limiting.md
index 28dda742f9..ac92f8c95c 100644
--- a/articles/appliance/dashboard/rate-limiting.md
+++ b/articles/appliance/dashboard/rate-limiting.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard Rate Limiting page
+topics:
+ - appliance
+ - dashboard
+ - rate-limiting
+conceptType: concept
+useCase: appliance
+applianceId: appliance23
+sitemap: false
---
# Auth0 Appliance Dashboard: Rate Limiting
diff --git a/articles/appliance/dashboard/settings.md b/articles/appliance/dashboard/settings.md
index 6fd0f9a013..842e959bdc 100644
--- a/articles/appliance/dashboard/settings.md
+++ b/articles/appliance/dashboard/settings.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard Settings page
+topics:
+ - appliance
+ - dashboard
+ - settings
+contentType: reference
+useCase: appliance
+applianceId: appliance24
+sitemap: false
---
# Auth0 Appliance Dashboard: Settings
@@ -70,13 +78,22 @@ The Settings page is broken down into the following sections:
* **MFA Session Absolute Timeout**: the absolute time window for which the user can have an MFA session. After this period of time elapses, the user will be prompted again for MFA;
* **MFA Session Inactive Timeout**: the maximum time window for which the user can have an MFA session without logging in again. If the user logs in prior to the expiration of this time period, the window will be extended.
-## Update Settings
+### Units of time
-* **Update Proxy**: unless your specific configuration is set up for offline updates, please leave this field blank.
+When providing time values to Auth0, please use the following abbreviations to ensure the correct units are used:
-## Monitoring
+| Abbreviation | Description |
+| - | - |
+| w | weeks |
+| d | days |
+| h | hours |
+| m | minutes |
+| s | seconds |
+| ms | milliseconds |
-* **New Relic License Key**: if you use New Relic for monitoring, enter your license key here to monitor your PSaaS Appliance instances.
+## Update Settings
+
+* **Update Proxy**: unless your specific configuration is set up for offline updates, please leave this field blank.
## API Keys
@@ -88,7 +105,7 @@ The Settings page is broken down into the following sections:
## Advanced Settings
-* **Enable Large Cookie Size**: if enabled, cookies larger than 4kb will be permitted (this might be required for protocols such as SAML and WS-Federation).
+* **Enable Large Cookie Size**: if enabled, cookies larger than 4kb will be permitted (this might be required for protocols such as SAML and WS-Federation).
* **Max Custom Database Timeout**: the maximum time allowed in seconds to make a query to your database (in seconds) for a custom database connection.
## Deprecated
diff --git a/articles/appliance/dashboard/tenants.md b/articles/appliance/dashboard/tenants.md
index 11a33b57b3..120e7b9073 100644
--- a/articles/appliance/dashboard/tenants.md
+++ b/articles/appliance/dashboard/tenants.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard Tenants page
+topics:
+ - appliance
+ - dashboard
+ - tenants
+contentType: reference
+useCase: appliance
+applianceId: appliance25
+sitemap: false
---
# PSaaS Appliance Dashboard: Tenants
@@ -27,7 +35,11 @@ For each associated tenant, you will see the following pieces of information:
The name column of the Tenants page is a hyperlink. Clicking on this brings up the page where you can set up custom domains for this particular tenant, as well overview information for any currently-existing custom domains.
-### Adding a Custom Domain
+### Adding a Custom Domain (legacy PSaaS customers only)
+
+::: note
+The following steps are only required for legacy PSaaS customers. All new customers can use the Custom Domains feature as implemented in the public cloud version.
+:::
To add a custom domain, click on the "Add Domain" button. You will be prompted for the following information:
diff --git a/articles/appliance/dashboard/troubleshoot.md b/articles/appliance/dashboard/troubleshoot.md
index 1664bd5e48..7af19b48fc 100644
--- a/articles/appliance/dashboard/troubleshoot.md
+++ b/articles/appliance/dashboard/troubleshoot.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard Troubleshoot page
+topics:
+ - appliance
+ - dashboard
+ - troubleshooting
+contentType: reference
+useCase: appliance
+applianceId: appliance26
+sitemap: false
---
# PSaaS Appliance Dashboard: Troubleshoot
diff --git a/articles/appliance/dashboard/updates.md b/articles/appliance/dashboard/updates.md
index e11db153d3..a78879ad02 100644
--- a/articles/appliance/dashboard/updates.md
+++ b/articles/appliance/dashboard/updates.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of the PSaaS Appliance Dashboard Updates page
+topics:
+ - appliance
+ - dashboard
+ - updates
+contentType: reference
+useCase: appliance
+applianceId: appliance27
+sitemap: false
---
# PSaaS Appliance Dashboard: Updates
@@ -11,9 +19,9 @@ description: Overview of the PSaaS Appliance Dashboard Updates page
The Updates page of the PSaaS Appliance configuration area allows you to make the required/selected updates to your PSaaS Appliance instance.
-::: note
- Updates cannot be rolled back/undone, so take VM snapshots and make backups as needed.
-:::
+Auth0 recommends taking VM snapshots and backups prior to beginning an upgrade. If there are issues with you upgrade, it might be possible to roll back the PSaaS Appliance to the version used immediately prior to the upgrade (this is the preferred option, since there would not be any data loss).
+
+However, if the option of rolling back to the existing version is not possible, Auth0 will need to restore your environment using the VM snapshots created prior to the update (there will be some data loss in this instance).

@@ -27,5 +35,5 @@ Once you have selected the appropriate build, any **release notes** applicable w
To begin the update, click on "Update from Internet." You will be prompted once more to confirm to ensure that the appropriate backups have been made, since PSaaS Appliance updates cannot be undone.
::: note
-You should schedule Production updates with your Auth0 Customer Success Manager so that there is an Auth0 Customer Success Engineer available in case any patches need to be manually applied. For more information on updates, see [Updating the PSaaS Appliance](/appliance/admin/updating-the-appliance).
+You should schedule Production updates with your Auth0 Technical Account Manager so that there is an Auth0 Customer Success Engineer available in case any patches need to be manually applied. For more information on updates, see [Updating the PSaaS Appliance](/appliance/admin/updating-the-appliance).
:::
diff --git a/articles/appliance/disaster-recovery-raci.md b/articles/appliance/disaster-recovery-raci.md
index 70716392b1..4a9e440e7b 100644
--- a/articles/appliance/disaster-recovery-raci.md
+++ b/articles/appliance/disaster-recovery-raci.md
@@ -1,6 +1,14 @@
---
description: An in-depth summary of the roles and responsibilities allocated between Auth0 and the subscriber
section: appliance
+topics:
+ - appliance
+ - disaster-recovery
+ - raci
+contentType: reference
+useCase: appliance
+applianceId: appliance55
+sitemap: false
---
@@ -47,7 +55,7 @@ The following table details the task division for configuring, creating, and mon
Download PSaaS Appliance CLI tool
C
R, A
-
The subscriber will need to contact their Auth0 Customer Success Manager for the custom download link.
+
The subscriber will need to contact their Auth0 Technical Account Manager for the custom download link.
Install PSaaS Appliance CLI Tool
@@ -118,7 +126,7 @@ The following table details the task division for configuring, creating, and mon
Restore the Data Backup
R, C
I
-
Please open a ticket in the Auth0 Support Center to request assistance with restoring a backup. Auth0 Customer Success Engineers will review your request, and if necessary, partner with the subscriber's infrastructure engineers to restore the environment. Please note that, in certain cases, a Professional Services fee may apply.
+
Please open a ticket in the Auth0 Support Center to request assistance with restoring a backup. Auth0 Customer Success Engineers will review your request, and if necessary, partner with the subscriber's infrastructure engineers to restore the environment. Please note that, in certain cases, a Professional Services fee may apply.
@@ -149,12 +157,18 @@ The following table details the task division for configuring, creating, and mon
R, A
The subscriber is responsible for restoring a VM Snapshot..
+
+
Recover Auth0 Environment
+
R
+
I, A
+
Auth0 is responsible for recovering the authentication environment.
+
## Backup Cadence Recommendations
-Auth0 recommends backing up your data on a daily basis (usually overnight to lessen impact on performance). However, if you need greater assurance of up-to-date data or have concerns about a logical data corruption, you might choose to backup more frequently. If this is the case, please contact your Auth0 Customer Success Manager to schedule a discussion, since the backup process puts a substantial load on the backup node and may impact your Production environment.
+Auth0 recommends backing up your data on a daily basis (usually overnight to lessen impact on performance). However, if you need greater assurance of up-to-date data or have concerns about a logical data corruption, you might choose to backup more frequently. If this is the case, please contact your Auth0 Technical Account Manager to schedule a discussion, since the backup process puts a substantial load on the backup node and may impact your Production environment.
Auth0 recommends taking **weekly** Virtual Machine Snapshots.
diff --git a/articles/appliance/disaster-recovery.md b/articles/appliance/disaster-recovery.md
index eae11b6b8a..a2296865d2 100644
--- a/articles/appliance/disaster-recovery.md
+++ b/articles/appliance/disaster-recovery.md
@@ -1,11 +1,18 @@
---
description: High-level overview of disaster recovery options for the PSaaS Appliance
section: appliance
+topics:
+ - appliance
+ - disaster-recovery
+contentType: concept
+useCase: appliance
+applianceId: appliance56
+sitemap: false
---
# PSaaS Appliance: Disaster Recovery
-When preparing for the possibility of issues with your PSaaS Appliance instances, your options depend on your tolerance for downtime. Below, you will find a discussion of the advantages and disadvantages associated with the various disaster recovery (DR) options available.
+When preparing for the possibility of issues with your PSaaS Appliance instances, your options depend on your tolerance for downtime. Below, you will find information on the advantages and disadvantages associated with the various disaster recovery (DR) options available.
Additionally, there is a difference between PSaaS Appliance availability and data availability/recovery. For example, the standard three-node cluster deployment has high availability and can survive a single-node failing. However, in cases of a data center failure or a logical data corruption, you would need a disaster recovery solution to help recover from that.
@@ -13,13 +20,15 @@ In cases where the data centers have very low latency, you can run individual PS
## Geographic High-Availability PSaaS Appliance Implementation
-If your requirements demand very little to no downtime, we recommend a [Geographic High-Availability PSaaS Appliance](/appliance/geo-ha) implementation. This is the only implementation that has automatic failover with recovery on the order of 1 minute.
+If your requirements demand regional resilience with little downtime, we recommend a [Geographic High-Availability PSaaS Appliance](/appliance/geo-ha) implementation. This is the only implementation that has failover between regions.
+
+Issue detection and failover typically occur at the database level in 30 seconds or less. However, switching over and rerouting traffic from one data center to another is an expensive operation, so we've configured the infrastructure to detect false positives and *not* switch over if one occurs. This secondary detection process reroutes client traffic through failure detection time-out mechanisms that result in an *effective* failover time of approximately ten minutes.
**Advantages**:
-Geo-HA is an PSaaS Appliance implementation that provides:
+Geo-HA is a PSaaS Appliance implementation that provides:
* Data center redundancy;
-* Automatic failure handling;
+* Rapid failure response;
* The highest form of PSaaS Appliance availability offered by Auth0.
**Disadvantages**:
@@ -28,35 +37,33 @@ Geo-HA involves:
* A higher cost due to increased complexity;
* Additional PSaaS Appliance Virtual Machines (VM) that need maintenance;
* An additional layer in front of the load balancer for GEO failover, such as F5 Global Traffic Manager or AWS Route 53;
-* Additional configuration to handle logical corruption, since this is not a scenario that is covered by the typical setup.
+* Additional configuration to handle logical corruption.
For more information, please see:
* [Geo HA](/appliance/geo-ha)
* [Disaster Recovery](/appliance/geo-ha/disaster-recovery)
## VM Snapshots
-If you have some tolerance for downtime (either in terms of minutes or hours), you can consider using the Virtual Machine (VM) snapshot approach. A VM snapshot contains everything you need to rebuild an PSaaS Appliance. You would be responsible for regularly taking VM snapshots and either storing them either offsite or replicating them to other regions in the cloud.
+If you have some tolerance for downtime (either in terms of minutes or hours), you can consider using the Virtual Machine (VM) snapshot approach. A VM snapshot contains everything needed to rebuild a PSaaS Appliance. You would be responsible for regularly taking VM snapshots and either storing them either offsite or replicating them to other regions in the cloud.
**Advantages**:
-* Recovery via VM snapshots is faster than using database backups (though the process is slower than GEO-HA).
-* You may not need manual intervention from an Auth0 Customer Success Engineer (CSE) to restore your cluster.
+* Recovery via VM snapshots is quicker than using database backups (though the process is slower than GEO-HA).
**Disadvantages**:
-* VM snapshots can become very large in size (snapshots are not compressed, and you would need a snapshot of each VM/drive), which makes storage tricky.
+* You will need manual intervention from an Auth0 Managed Services Engineer (MSE) to restore your cluster.
+* VM snapshots can become very large (snapshots are not compressed, and you would need a snapshot of each VM/drive), which makes storage tricky.
* The backup and recovery process requires manual intervention.
### Basic Steps for Recovering with VM Snapshots
-The following outlines the basic steps required for restoring your PSaaS Appliance instances using VM snapshots:
+The following outlines the basic steps required for restoring PSaaS Appliance instances using VM snapshots:
1. Ensure that you have a snapshot of your VM(s) and that it is stored at a secondary site. In the event of a disaster, your primary site may not be accessible.
2. Restore your VM(s) using your snapshots at your secondary site.
-Use the [PSaaS Appliance Command Line Interface (CLI)](/appliance/cli) to [reconfigure the IP addresses](/appliance/cli/reconfiguring-ip) of the VM(s).
+3. Contact a Managed Services Engineer via support ticket to complete the recovery of your environment
::: panel VMWare's Site Recovery Manager
-If you are hosting your PSaaS Appliance instances using VMware, you may also implement a similar backup/recovery scenario using VMWare's Site Recovery Manager (SRM). SRM provides an automated mechanism to move your snapshots to a secondary site, where they can be retrieved if you ever need your data restored. If you choose this option, Auth0 will help you set up and test your implementation.
-
-We have tested that it will change the IP for the box and you can [run re-ip](/appliance/cli/reconfiguring-ip) as long as you have prepared the [PSaaS Appliance Command Line Interface (CLI)](/appliance/cli) ahead of time and uploaded the certificate.
+Site Recovery Manager is not supported on current versions of Auth0 PSaaS Appliance. If you rely on this VMWare feature, please contact your Technical Account Manager for guidance.
:::
## Database Backups
@@ -71,7 +78,7 @@ If you choose to use database backups as your DR strategy, please note that this
* Database backups are smaller and easier to move offsite than VM snapshots.
**Disadvantage**:
-* You will need manual intervention from an Auth0 CSE to restore your PSaaS Appliance.
+* You will need manual intervention from an Auth0 MSE to restore your PSaaS Appliance.
* Recovering with a database backup requires the greatest amount of time.
For more information, please see:
@@ -79,12 +86,8 @@ For more information, please see:
* [Using the CLI to Backup PSaaS Appliance Instances](/appliance/cli/backing-up-the-appliance)
* [Adding an PSaaS Appliance Node to the Backup Role](/appliance/cli/adding-node-to-backup-role)
-::: note
- This option is available to PSaaS Appliance on version **7247** or later.
-:::
-
## Combining VM Snapshots and Database Backups
-A middle ground between using VM snapshots and database backups is to take weekly VM snapshots, while scheduling nightly database backups.
+A middle ground between using VM snapshots and database backups is to take weekly VM snapshots while scheduling nightly database backups.
The recovery process still requires the assistance of an Auth0 CSE, but because the VMs can be automatically restored, only the database needs manual intervention/assistance. This eliminates some of the downtime resulting from using just database backups.
diff --git a/articles/appliance/extensions.md b/articles/appliance/extensions.md
index b831ea59ee..b98480d9b1 100644
--- a/articles/appliance/extensions.md
+++ b/articles/appliance/extensions.md
@@ -2,23 +2,34 @@
url: /appliance/extensions
section: appliance
description: Explains implementation details for Extensions specific to the PSaaS Appliance.
+topics:
+ - appliance
+ - extensions
+contentType:
+ - concept
+ - how-to
+useCase: appliance
+applianceId: appliance58
+sitemap: false
---
# PSaaS Appliance: Extensions
While using [Extensions](/extensions) in the PSaaS Appliance is very similar to using Extensions in the multi-tenant installation of Auth0, there are some differences.
-## Configure Extensions
+You may receive updates to Extensions at any time without prior notice.
-Extensions make use of Webtasks. When you activate a Webtask in the PSaaS Appliance, you get a URL specific to that instance of the Webtask service. By default, this URL is structured as follows:
+## Set up and enable Webtasks
-`webtask.`
+You must set up and enable Webtasks before you can use Extensions.
-::: note
-To enable Webtasks, go to the [Webtasks Settings page of the Management Dashboard](${manage_url}/#/account/webtasks).
+To [set up and enable your Webtasks](/appliance/infrastructure/extensions#requirements-for-enabling-webtasks), go to the [Webtasks page under Tenant Settings](${manage_url}/#/tenant/webtasks) in the Management Dashboard.
+
+## Configure Extensions
-See [Enable Webtasks, Web Extensions, and User Search](/appliance/infrastructure/extensions) for additional information.
-:::
+When you activate a Webtask in the PSaaS Appliance, you get a URL specific to that instance of the Webtask service. By default, this URL is structured as follows:
+
+`webtask.`
In order for you to configure Extensions, you will need to add this URL to the **Allowed Origins (CORS)** section under the [Auth0 Dashboard's Application Settings page](${manage_url}/#/applications).
@@ -32,4 +43,6 @@ The [Delegated Administration](/extensions/delegated-admin) extension is availab
## Dedicated Domains
-Beginning with PSaaS Appliance version `13451`, you may now configure Webtask on a [dedicated domain](/appliance/webtasks/dedicated-domains). This enables you to safely use extensions in multi-tenant environments (the behavior is akin to that of the Auth0 Public Cloud Service).
\ No newline at end of file
+Beginning with PSaaS Appliance version `13451`, you may now configure Webtask on a [dedicated domain](/appliance/webtasks/dedicated-domains). This enables you to safely use extensions in multi-tenant environments (the behavior is akin to that of the Auth0 Public Cloud Service).
+
+If you are planning on using Extensions, you **must** implement Webtask dedicated domains.
diff --git a/articles/appliance/geo-ha/disaster-recovery.md b/articles/appliance/geo-ha/disaster-recovery.md
index 7f23338be2..8750ac5517 100644
--- a/articles/appliance/geo-ha/disaster-recovery.md
+++ b/articles/appliance/geo-ha/disaster-recovery.md
@@ -1,6 +1,13 @@
---
section: appliance
description: Descriptions of PSaaS Appliance Geo HA Failure Scenarios and Testing
+topics:
+ - appliance
+ - geo-ha
+contentType: reference
+useCase: appliance
+applianceId: appliance28
+sitemap: false
---
@@ -70,7 +77,7 @@ The following table details some of the ways in which the Geographic High-Availa
Connection between the Global Load Balancer and the Primary Site Unavailable
-
All requests are routed to the secondary site, but the secondary nodes continue to use data on the primary site
+
All requests are routed to the secondary site, but the secondary nodes continue to use data on the primary site.
Some performance degradation due to cross-geography data requests.
@@ -95,7 +102,7 @@ The following table details some of the ways in which the Geographic High-Availa
To test the Geographic High-Availability PSaaS Appliance (GEO HA) failover/failback procedure, you should:
-1. Take all nodes in the primary data center offline.
+1. Take all nodes in the primary data center offline;
2. Run tests against the global load balancer to ensure that traffic gets rerouted to the secondary site.
GEO HA does not support having both the primary and secondary sites disconnected and active at the same time. Because the data layer is arranged in one stretched cluster, the cluster only permits one data node to act as primary.
@@ -110,7 +117,7 @@ As a customer, it is your responsibility to perform regular backups on your Geog
Typically, Auth0 recommends performing a daily backup. However, if you have concerns about a logical data corruption, or you need greater assurance of up-to-date data, you might choose to backup more frequently.
-Because the backup process puts a substantial load on the backup node, please contact your Auth0 Customer Success Manager to schedule a discussion about performance impact if backups are performed more frequently/during peak usage times.
+Because the backup process puts a substantial load on the backup node, please contact your Auth0 Technical Account Manager to schedule a discussion about performance impact if backups are performed more frequently/during peak usage times.
## Further Reading
diff --git a/articles/appliance/geo-ha/dr-overview.md b/articles/appliance/geo-ha/dr-overview.md
index 073d13f585..32051a5492 100644
--- a/articles/appliance/geo-ha/dr-overview.md
+++ b/articles/appliance/geo-ha/dr-overview.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Descriptions of PSaaS Appliance Geo HA Failure and Disaster Recovery
+topics:
+ - appliance
+ - geo-ha
+ - disaster-recovery
+contentType: reference
+useCase: appliance
+applianceId: appliance29
+sitemap: false
---
diff --git a/articles/appliance/geo-ha/index.md b/articles/appliance/geo-ha/index.md
index c14393f61e..16329c8635 100644
--- a/articles/appliance/geo-ha/index.md
+++ b/articles/appliance/geo-ha/index.md
@@ -2,11 +2,21 @@
url: /appliance/geo-ha
section: appliance
description: Descriptions of Appliance Geo HA
+topics:
+ - appliance
+ - geo-ha
+ - disaster-recovery
+contentType:
+ - index
+ - reference
+useCase: appliance
+applianceId: appliance30
+sitemap: false
---
# Private SaaS (PSaaS) Appliance: High Availability Geo Cluster (Geo HA)
-The high availability geo cluster is a PSaaS Appliance implementation that provides data center redundancy and automatic failure handling. This is the highest form of PSaaS Appliance availability offered by Auth0.
+The high availability geo cluster is a PSaaS Appliance implementation that provides regional data center redundancy and rapid failure response. This is the highest form of PSaaS Appliance availability offered by Auth0.
## Overview
@@ -37,6 +47,8 @@ The Arbiter does not store data or execute application logic, but acts as a witn
Since the Arbiter isn’t storing data and doesn’t run any services, it can be a small instance with two cores and 4GB of memory.
+You must enable outbound [internet connectivity](/appliance/infrastructure/network#internet-connectivity) from the Arbiter for system updates.
+
### Global Load Balancer/DNS Failover Configuration
You will need to deploy a global load balancer that supports an active/standby configuration. This will be configured to begin using the secondary site if the primary site load balancer is unavailable.
diff --git a/articles/appliance/index.html b/articles/appliance/index.html
index 1335704513..56af4b1bc2 100644
--- a/articles/appliance/index.html
+++ b/articles/appliance/index.html
@@ -3,13 +3,18 @@
section: appliance
classes: topic-page
title: PSaaS Appliance
+topics:
+ - appliance
+useCase: appliance
+applianceId: appliance59
+sitemap: false
---
Private SaaS (PSaaS) Appliance
- An Auth0 deployment that exists in a dedicated area of Auth0's cloud, your cloud, or your own data center.
+ An Auth0 deployment that exists in a dedicated area of Auth0's cloud or your AWS cloud.
- In addition to providing tools for monitoring your PSaaS Appliance instances, Auth0 provides integration with select third-party utilities.
+ Learn how to monitor your PSaaS Appliance instances, so that you always know how it is performing.
@@ -113,12 +118,6 @@
PSaaS Appliance Administration
The PSaaS Appliance Command Line Interface (CLI) allows you to perform operations on your PSaaS Appliance via authorized workstations.
- If your business needs require you to create tenants regularly, you may automate this process in your PSaaS Appliance instances. For example, you might need to create one tenant for each customer or project that goes live.
-
diff --git a/articles/appliance/infrastructure/dns.md b/articles/appliance/infrastructure/dns.md
index 24a8b7d1c9..2466fa2ca1 100644
--- a/articles/appliance/infrastructure/dns.md
+++ b/articles/appliance/infrastructure/dns.md
@@ -1,6 +1,14 @@
---
section: appliance
description: PSaaS Appliance infrastructure information about DNS
+topics:
+ - appliance
+ - infrastructure
+ - dns
+contentType: reference
+useCase: appliance
+applianceId: appliance31
+sitemap: false
---
@@ -25,11 +33,11 @@ Dedicated and non-dedicated host names must be unique.
Management Dashboard
-
manage-project.yourdomain.com
+
manage.yourdomain.com
Configuration
-
config-project.yourdomain.com
+
config.yourdomain.com
Webtask
@@ -37,30 +45,30 @@ Dedicated and non-dedicated host names must be unique.
App Tenant(s)
-
app1-project.yourdomain.com; app2-project.yourdomain.com ...and so on
+
identity.yourdomain.com (for example); app-project.yourdomain.com (if you want more than 1 App tenant) ...and so on
-For a dev/test non-production PSaaS Appliance a common practice is to append “-dev” to the hostname component in the domain name:
+For a dev/test non-production PSaaS Appliance a common practice is to include "dev” in the domain name:
Management Dashboard (Dev)
-
manage-dev-project.yourdomain.com
+
manage.dev.yourdomain.com
Configuration (Dev)
-
config-dev-project.yourdomain.com
+
config.dev.yourdomain.com
Webtask (Dev)
-
webtask-dev.yourdomain.com
+
webtask.dev.yourdomain.com
App Tenant(s) (Dev)
-
app1-dev-project.yourdomain.com; app2-dev-project.yourdomain.com ...and so on
+
identity.dev.yourdomain.com (for example); app-name.dev.yourdomain.com (if you want more than 1 App tenant) ...and so on
@@ -69,7 +77,6 @@ For a dev/test non-production PSaaS Appliance a common practice is to append “
* **Configuration**: highly-privileged tenant used to do the PSaaS Appliance baseline configuration and for managing the security of other tenants;
* **App**: the name of your application;
-* **Project**: the name of the overarching project or department;
* **yourdomain.com**: your organization's domain name.

@@ -181,4 +188,4 @@ Suppose these were your standard domains:
-Please note that all tenant names are derived from the base Configuration Tenant. However, you may set your custom domain to point toward any of your tenants (in the example above, `new-name.not-example.com` maps to `auth.example.com`, and the latter may be used by your applications).
\ No newline at end of file
+Please note that all tenant names are derived from the base Configuration Tenant. However, you may set your custom domain to point toward any of your tenants (in the example above, `new-name.not-example.com` maps to `auth.example.com`, and the latter may be used by your applications).
diff --git a/articles/appliance/infrastructure/extensions.md b/articles/appliance/infrastructure/extensions.md
index 04a15fb0ea..f2a2e22e74 100644
--- a/articles/appliance/infrastructure/extensions.md
+++ b/articles/appliance/infrastructure/extensions.md
@@ -1,64 +1,76 @@
---
section: appliance
description: PSaaS Appliance infrastructure information about enabling Webtasks and Extensions
+topics:
+ - appliance
+ - infrastructure
+ - extensions
+contentType:
+ - Reference
+useCase: appliance
+applianceId: appliance32
+sitemap: false
---
# Enable Webtasks, Extensions, and User Search
-Beginning with version `8986`, the PSaaS Appliance supports extensions. This is in addition to support for [Webtasks](appliance/webtasks).
+The PSaaS Appliance supports:
-::: note
-Some of the [Extensions](/extensions) available to users of the Auth0 public cloud are unavailable in the PSaaS Appliance. As such, these do not appear as options in the PSaaS Appliance's Dashboard.
-:::
+* Extensions
+* [Webtasks](appliance/webtasks)
+* User search using Elasticsearch
-Beginning with version `10755`, the PSaaS Appliance supports User Search using Elasticsearch. This allows you to use extensions that require User Search, including the [Delegated Admininstration extension](/extensions/delegated-admin)
+## Extensions
-## Requirements for Enabling User Search
+You can find a list of extensions available to you [in the Dashboard](${manage_url}/#/extensions).
-To enable User Search, you must increase the amount of storage available in your Development and Production environments.
+Some of the [Extensions available to users of the Auth0 public cloud](/extensions) are unavailable in the PSaaS Appliance. As such, these do not appear as options in the PSaaS Appliance's Dashboard.
-* If you have a *single non-Production/Development node*, you need an additional **50 GB** drive;
-* If you have a *three-node Production cluster*, you need an additional **100 GB** drive on *each* of your three Virtual Machines;
-* If you have a *Geographic High-Availability implementation*, you need an additional **100 GB** drive on *each* of your data nodes in the primary and secondary data centers.
+## Webtasks Requirements
-For all other configuration types, please consult with your Customer Success Engineer.
-
-## Enabling User Search
-
-Once you have added the additional drive(s), submit a Support ticket to request that Auth0:
-
-* Enable User Search;
-* Update your PSaaS Appliance to version `10755` or above. Auth0 will work with you to upgrade your Development environment first, so that you can test the changes. Auth0 will coordinate the Production upgrade after you've concluded testing in Development.
-
-## Requirements for Enabling Webtasks
-
-Your Development and/or Production environments must meet the following requirements before you can enable Webtasks and update to version `8986` or above.
+Your Development and Production environments must meet the following requirements before you can enable Webtasks:
* All nodes in the cluster have outbound access using **Port 443** to:
* `docker.it.auth0.com` (or `52.9.124.234`)
- * Please note that version 8293 required outbound access to `docker.it.auth0.com` (or `52.9.124.234`) on Port **5000**.
* `cdn.auth0.com`
-* All nodes are able to communicate with other nodes in the same cluster using ports **8721** and **8701**.
+* All nodes can communicate with other nodes in the same cluster using ports **8721** and **8701**.
* All [SSL certificates](/appliance/infrastructure/security#ssl-certificates) have the appropriate Webtask DNS entry. Examples:
* `webtask..com`
* `webtask-dev..com`
-## Enabling Webtasks
-
-Once you have met the requirements for enabling Webtasks, submit a Support ticket to request that Auth0:
+## Enable Webtasks
-* Configure Webtasks (including switching your sandbox mode to `auth0-sandbox`)
-* Update your PSaaS Appliance to version `8986`. Auth0 will work with you to upgrade your Development environment first, so that you can test the changes. Afterwards, Auth0 will coordinate the Production upgrade.
+Once you have met the requirements for enabling Webtasks, submit a Support ticket to request that Auth0 configure Webtasks on your behalf.
## Dedicated Domains
-Beginning with PSaaS Appliance version `13451`, you may now configure Webtask on a [dedicated domain](/appliance/webtasks/dedicated-domains). This enables you to safely use extensions in multi-tenant environments (the behavior is akin to that of the Auth0 Public Cloud Service).
+You may configure Webtasks on a [dedicated domain](/appliance/webtasks/dedicated-domains). Using dedicated domains enables you to safely use extensions in multi-tenant environments (the behavior is akin to that of the Auth0 Public Cloud Service).
+
+If you are planning on using Extensions, you **must** implement Webtask dedicated domains.
+
+## User search
+
+The PSaaS Appliance supports User Search using Elasticsearch. This allows you to use extensions that require user search functionality, including the [Delegated Administration extension](/extensions/delegated-admin).
+
+### Requirements for enabling user search
+
+To enable User Search, you must increase the amount of storage available in your Development and Production environments.
+
+* If you have a *single non-Production/Development node*, you need an additional **50 GB** drive;
+* If you have a *three-node Production cluster*, you need an extra **100 GB** drive on *each* of your three Virtual Machines;
+* If you have a *Geographic High-Availability implementation*, you need an additional **100 GB** drive on *each* of your data nodes in the primary and secondary data centers.
+
+For all other configuration types, please consult with your Customer Success Engineer.
+
+## Enabling User Search
+
+Once you have added the additional drive(s), submit a Support ticket to request that Auth0 enable User Search.
## Keep reading
::: next-steps
* [IP Address and Port Requirements](/appliance/infrastructure/ip-domain-port-list)
* [Extensions](/extensions)
-* [Delegated Admininstration extension](/extensions/delegated-admin)
+* [Delegated Administration extension](/extensions/delegated-admin)
* [Webtasks](/appliance/webtasks)
* [Version Change Logs](https://auth0.com/changelog/appliance)
:::
diff --git a/articles/appliance/infrastructure/faq.md b/articles/appliance/infrastructure/faq.md
index 0286f7c2da..e9dc9fc33e 100644
--- a/articles/appliance/infrastructure/faq.md
+++ b/articles/appliance/infrastructure/faq.md
@@ -1,6 +1,13 @@
---
description: This page answers several common questions regarding the PSaaS Appliance infrastructure.
section: appliance
+topics:
+ - appliance
+ - infrastructure
+contentType: reference
+useCase: appliance
+applianceId: appliance33
+sitemap: false
---
# PSaaS Appliance Infrastructure Requirements: Frequently Asked Questions
@@ -23,7 +30,9 @@ No, the PSaaS Appliance is a managed service that runs within your network. You
While this is currently not supported, preinstalled anti-virus software may be included in future updates.
#### Will Auth0 provide me with a CSR file for my SSL Certificate?
-If Auth0 hosts the PSaaS Appliance, Auth0 will provide the required certificate(s).
+No. The details of generating certificates, such as a CSR, vary among public certificate providers. Please work with your public certificate authority for these requirements.
+
+If Auth0 hosts the PSaaS Appliance, Auth0 will provide the required `*.auth0.com` SSL certificates.
#### Why do both the DEV (non-prod) node and PROD cluster require unique certificates signed by a public Certificate Authority?
Webtasks and web extensions require this due to Node.js security requirements.
@@ -74,7 +83,6 @@ Auth0 requires [remote access](/appliance/remote-access-options) to your PSaaS A
1. Jumphost + Firewall Whitelist
2. Two Jumphosts
-3. VPN
We do not support other methods, such as VDI or Screen Sharing mechanisms.
@@ -90,4 +98,4 @@ You can read the PSaaS Appliance terms [here](https://auth0.com/legal/baseline/P
#### Does the PSaaS Appliance require internet access?
-Please refer to [our documentation on the internet-related requirements](/appliance/infrastructure/internet-restricted-deployment) for the PSaaS Appliance.
\ No newline at end of file
+Please refer to [our documentation on the internet-related requirements](/appliance/infrastructure/internet-restricted-deployment) for the PSaaS Appliance.
diff --git a/articles/appliance/infrastructure/index.md b/articles/appliance/infrastructure/index.md
index 44b51cc621..6f2919f464 100644
--- a/articles/appliance/infrastructure/index.md
+++ b/articles/appliance/infrastructure/index.md
@@ -3,6 +3,15 @@ title: PSaaS Appliance Infrastructure Requirements
url: /appliance/infrastructure
section: appliance
description: This document contains information about the PSaaS Appliance and its infrastructure requirements.
+topics:
+ - appliance
+ - infrastructure
+contentType:
+ - index
+ - reference
+useCase: appliance
+applianceId: appliance34
+sitemap: false
---
# Private SaaS (PSaaS) Appliance Infrastructure Requirements
diff --git a/articles/appliance/infrastructure/infrastructure-overview.md b/articles/appliance/infrastructure/infrastructure-overview.md
index 2a949d7a43..b9e92e633a 100644
--- a/articles/appliance/infrastructure/infrastructure-overview.md
+++ b/articles/appliance/infrastructure/infrastructure-overview.md
@@ -1,6 +1,13 @@
---
section: appliance
description: PSaaS Appliance infrastructure overview
+topics:
+ - appliance
+ - infrastructure
+contentType: concept
+useCase: appliance
+applianceId: appliance35
+sitemap: false
---
# PSaaS Appliance Deployment Architecture
diff --git a/articles/appliance/infrastructure/installation.md b/articles/appliance/infrastructure/installation.md
index 36c641b829..4197c25fc8 100644
--- a/articles/appliance/infrastructure/installation.md
+++ b/articles/appliance/infrastructure/installation.md
@@ -1,6 +1,16 @@
---
section: appliance
description: PSaaS Appliance infrastructure information about installation
+topics:
+ - appliance
+ - infrastructure
+ - installation
+contentType:
+ - concept
+ - how-to
+useCase: appliance
+applianceId: appliance36
+sitemap: false
---
@@ -42,11 +52,10 @@ Auth0 provides a project plan methodology to help customers get up and running w
The following basic steps are required to get the infrastructure up and running and the PSaaS Appliance deployed:
-1. Understand the PSaaS Appliance infrastructure requirements as detailed in this document;
-2. Complete and submit the [Pre-PSaaS Appliance Installation Checklist](https://docs.google.com/forms/d/e/1FAIpQLSckWRi2MWpzhBkUXoqjaEzMPGUsyL4ICbOetcGvSnn64dSM-A/viewform?c=0&w=1) to ensure that you have everything you need ready and on hand for the PSaaS Appliance deployment;
-3. Access and install the PSaaS Appliance;
-4. Complete and submit the Post-PSaaS Appliance Install Checklist to notify Auth0 that you have everything in place and that Auth0 can commence configuring the PSaaS Appliance;
-5. Complete the steps detailed in the PSaaS Appliance Setup Guide.
+1. Understand the PSaaS Appliance infrastructure requirements as detailed in this document.
+2. Set up the infrastructure after the Appliance Project Manager has shared the required AMI file with you.
+3. Complete and submit the [PSaaS Appliance Install Checklist](https://docs.google.com/forms/d/e/1FAIpQLSckWRi2MWpzhBkUXoqjaEzMPGUsyL4ICbOetcGvSnn64dSM-A/viewform?c=0&w=1) to notify Auth0 that you have the required infrastructure in place and that Auth0 can begin configuring the PSaaS Appliance.
+4. Meet with Auth0 to deploy the DEV and PROD environments (the Appliance Project Manager will set up this meeting).
## Development/Test/Production Lifecycle
diff --git a/articles/appliance/infrastructure/internet-restricted-deployment.md b/articles/appliance/infrastructure/internet-restricted-deployment.md
index 0823f734c7..352e6b0e36 100644
--- a/articles/appliance/infrastructure/internet-restricted-deployment.md
+++ b/articles/appliance/infrastructure/internet-restricted-deployment.md
@@ -1,8 +1,12 @@
---
title: Internet-Restricted PSaaS Appliance Deployments
description: Operating the PSaaS Appliance in an Internet-Restricted Environment
+contentType: reference
+useCase: appliance
+applianceId: appliance37
+sitemap: false
---
-# PSaaS Appliace Deployments with Limited Internet Connectivity
+# PSaaS Appliance Deployments with Limited Internet Connectivity
The Auth0 PSaaS Appliance is delivered as a managed service that can run in:
@@ -14,7 +18,7 @@ The PSaaS Appliance is designed to mirror the solutions offered via the Auth0 Pu
## Internet-Restricted Environments
-While we make an effort to create PSaaS Appliances that are encapsulated for normal operation, there are several features that require access to external resources for normal functionality. These resources are primarily located on the Auth0 Content Delivery Network (CDN).
+While we make an effort to create PSaaS Appliances that are encapsulated for normal operation, there are several features that require access to external resources for normal functionality. These resources are primarily located on the Auth0 Content Delivery Network (CDN), which is accessed via **cdn.auth0.com**.
::: warning
The PSaaS Appliance **must** have access to the internet during [update periods](https://auth0.com/docs/appliance/infrastructure/ip-domain-port-list#external-connectivity).
@@ -22,29 +26,41 @@ The PSaaS Appliance **must** have access to the internet during [update periods]
Operating the PSaaS Appliance in an internet-restricted environment results in the loss of the following features/functionality:
-* Management Dashboard
+* Analytics (including usage statistics)
+* Authentication API Explorer
+* [Extensions](/extensions)
+* [Hooks](/hooks)
* Lock
* Management API Explorer
-* Authentication API Explorer
+* Management Dashboard
* Quickstarts
* Social Connections
-* Analytics (including usage statistics)
### Management Dashboard
-The browser that you are using to manage your PSaaS Appliance requires internet access to navigate to the Management Dashboard (located at **manage.your-domain**).
+The browser that you are using to manage your PSaaS Appliance requires Internet access to navigate to the Management Dashboard (located at **manage.your-domain**).
You may, however, restrict server-side access to the Management Dashboard.
To properly render the Dashboard, it accesses the following sites:
-* **cdn.auth0.com**: resources loaded from this CDN are well-known and include CSS, JavaScript, and images
-* **fonts.googleapis.com**: resources loaded include CSS and font files
-* **s.gravatar.com** and **i2.wp.com**: resources include user profile images loaded from WordPress' Gravatar service
+* **cdn.auth0.com**: resources loaded from this CDN are well-known and include CSS, JavaScript, and images.
+* **fonts.googleapis.com**: resources loaded include CSS and font files.
+* **s.gravatar.com** and **i2.wp.com**: resources include user profile images loaded from WordPress' Gravatar service.
* **fast.fonts.net**: resources include CSS files for font support.
+### Multi-factor Authentication (MFA)
+
+When using multi-factor authentication (MFA), you will need Internet access for Push notifications, SMS, and Voice.
+
+For limited connectivity options, you may choose from:
+
+* One-time password with Google Authenticator, Authy or similar apps
+* A custom MFA implementation using redirect rules
+* Duo (on-premise versions only)
+
## Summary
The PSaaS Appliance requires access to specific external resources for normal functionality, and we do not recommend restricting access to these resources for optimal function. These resources are primarily located on the Auth0 CDN.
-Currently, there are no plans to reduce the reliance of the PSaaS Appliance on the Auth0 CDN.
\ No newline at end of file
+Currently, there are no plans to reduce the reliance of the PSaaS Appliance on the Auth0 CDN.
diff --git a/articles/appliance/infrastructure/ip-domain-port-list.md b/articles/appliance/infrastructure/ip-domain-port-list.md
index 2499ee38f2..d81d3d2a2f 100644
--- a/articles/appliance/infrastructure/ip-domain-port-list.md
+++ b/articles/appliance/infrastructure/ip-domain-port-list.md
@@ -1,11 +1,21 @@
---
description: PSaaS Appliance infrastructure information about IP/Domain and Port Usage
section: appliance
+topics:
+ - appliance
+ - infrastructure
+ - ip-addresses
+ - domains
+ - ports
+contentType: reference
+useCase: appliance
+applianceId: appliance38
+sitemap: false
---
-# PSaaS Appliance Infrastructure: IP/Domain and Port List
+# PSaaS Appliance Infrastructure Requirements: IP/Domain and Port List
The PSaaS Appliance requires certain ports within the cluster to be open and able to access each other, as well as selected external sites.
@@ -124,7 +134,7 @@ Auth0 strives to keep these IP addresses stable, though this is not a given. Fro
Updates
Outbound
apt-mirror.it.auth0.com (52.8.153.197)
-
80/443
+
443
Provides update packages for PSaaS Appliance instances
Yes
@@ -137,11 +147,11 @@ Auth0 strives to keep these IP addresses stable, though this is not a given. Fro
Yes
-
Web extensions and Management Dashboard
+
Web extensions, Hooks, and Management Dashboard
Outbound
cdn.auth0.com
443
-
Required to run web extensions; also required for admins to browse to the Management Dashboard
+
Required to run web extensions and Hooks; also required for admins to browse to the Management Dashboard
Yes
@@ -184,6 +194,14 @@ Auth0 strives to keep these IP addresses stable, though this is not a given. Fro
Required by the PSaaS Appliance to resolve host names internal and external to your environment
Yes
+
+
SMTP
+
Outbound
+
SMTP Server(s)
+
25/587
+
Allows sending of emails from the Appliance
+
No
+
diff --git a/articles/appliance/infrastructure/network.md b/articles/appliance/infrastructure/network.md
index 6185221b20..d197ad2191 100644
--- a/articles/appliance/infrastructure/network.md
+++ b/articles/appliance/infrastructure/network.md
@@ -1,6 +1,14 @@
---
section: appliance
description: PSaaS Appliance infrastructure information about Networks
+topics:
+ - appliance
+ - infrastructure
+ - networks
+contentType: reference
+useCase: appliance
+applianceId: appliance39
+sitemap: false
---
# PSaaS Appliance Infrastructure Requirements: Network
diff --git a/articles/appliance/infrastructure/security.md b/articles/appliance/infrastructure/security.md
index 88691636f4..adc6c39577 100644
--- a/articles/appliance/infrastructure/security.md
+++ b/articles/appliance/infrastructure/security.md
@@ -1,6 +1,14 @@
---
section: appliance
description: PSaaS Appliance infrastructure information about security
+topics:
+ - appliance
+ - infrastructure
+ - security
+contentType: reference
+useCase: appliance
+applianceId: appliance40
+sitemap: false
---
# PSaaS Appliance Infrastructure Requirements: Security and Access
@@ -9,7 +17,12 @@ description: PSaaS Appliance infrastructure information about security
## SSL Certificates
-You need to create and install a unique SSL certificate for each PSaaS Appliance (such as your production cluster, your development node, or your QA environment). You need additional certificates if your environments require [extensions](/extensions) or you use [custom domains](/appliance/custom-domains). If you are using extensions, please see [Webtask with Dedicated Domains](/appliance/webtasks/dedicated-domains).
+When using the PSaaS Appliance, you will need to provide several SSL certificates. You must create and install a unique SSL certificate for:
+
+* Each PSaaS Appliance (e.g., your production cluster, your development node, your QA environment)
+* [Extensions](/appliance/extensions)
+* [Custom Domains](/appliance/custom-domains)
+* [Webtasks](/appliance/webtasks) (with or without [Dedicated Domains](/appliance/webtasks/dedicated-domains))
::: note
If you are unsure of where to get SSL Certificates, please contact your network security team. They are usually the ones familiar with the required processes and working with the appropriate certificate authorities (CA) to generate new certificates.
@@ -17,8 +30,8 @@ You need to create and install a unique SSL certificate for each PSaaS Appliance
The SSL Certificate:
-* must be created by a public certificate authority. They cannot be self-signed.
-* may be a wildcard *or* a multi-domain (SAN) certificate;
+* must be created by a public certificate authority. They cannot be self-signed;
+* can be a wildcard *or* a multi-domain (SAN) certificate;
* must contain all required DNS/domain names, including those for the:
* Management Dashboard;
* Configuration Tenant;
@@ -44,6 +57,14 @@ PARENT
-----END CERTIFICATE-----
```
+If you're uploading the public and private keys separately, convert the private key to RSA as follows:
+
+```text
+-----BEGIN RSA PRIVATE KEY-----
+PRIVATE-KEY
+-----END RSA PRIVATE KEY-----
+```
+
## Transparent Proxies
If you are behind a transparent proxy, you will need to:
@@ -53,11 +74,11 @@ If you are behind a transparent proxy, you will need to:
## HTTPS or TLS
-Users must connect to the PSaaS Appliance using secure protocols (HTTPS or TLS). Depending on your network design, you could terminate the Secure Channel at the load balancer or at the PSaaS Appliance. In both cases your SSL/TLS certificate must be locally installed on the PSaaS Appliance.
+Users must connect to the PSaaS Appliance using secure protocols (HTTPS or TLS). Depending on your network design, you could terminate the Secure Channel at the load balancer or the PSaaS Appliance. In both cases, your SSL/TLS certificate must be locally installed on the PSaaS Appliance.
## SMTP
-You must configure an SMTP server in order for the PSaaS Appliance to send emails. The PSaaS Appliance requires an authentication SMTP server that has been configured with SMTP PLAIN authentication.
+You must configure an SMTP server for the PSaaS Appliance to send emails. The PSaaS Appliance requires an authentication SMTP server that has been configured with SMTP PLAIN authentication.
**AWS SES Users**: If your domain is not validated, you will not be able to send email with AWS SES.
@@ -71,8 +92,8 @@ Auth0 requires [remote access](/appliance/remote-access-options) to your PSaaS A
### Initial Configuration
-Auth0's remote access method for initial configuration requires SSH access via Jumphost (the preferred method) or via VPN. After the initial configuration, please feel free to disable this connection.
+Auth0's remote access method for initial configuration requires SSH access via Jumphost. After the initial setup, please feel free to disable this connection.
### Updates, Maintenance, and Troubleshooting
-Typically, updates are performed via the Auth0 Dashboard. In the event that Auth0 needs to remote in to identify and troubleshoot issues, an Auth0 Customer Success Engineer will need access to the PSaaS Appliance through SSH access via Jumphost (the preferred method) or over VPN. This connection may be enabled for and disabled after the agreed-upon time frames for work.
+Typically, updates are performed via the Auth0 Dashboard. If Auth0 needs to remote in to identify and troubleshoot issues, an Auth0 Customer Success Engineer will need access to the PSaaS Appliance through SSH access via Jumphost. This connection can be enabled for and disabled after the agreed-upon time frames for work.
diff --git a/articles/appliance/infrastructure/virtual-machines.md b/articles/appliance/infrastructure/virtual-machines.md
index 5095b5367e..45851327f6 100644
--- a/articles/appliance/infrastructure/virtual-machines.md
+++ b/articles/appliance/infrastructure/virtual-machines.md
@@ -1,15 +1,19 @@
---
section: appliance
description: PSaaS Appliance infrastructure information about virtual machines
+topics:
+ - appliance
+ - infrastructure
+ - virtual-machines
+contentType: reference
+useCase: appliance
+applianceId: appliance41
+sitemap: false
---
# PSaaS Appliance Infrastructure Requirements: Virtual Machines
-You may deploy the PSaaS Appliance on your premises using your own infrastructure or the infrastructure of a cloud provider. Currently, Auth0 supports the following PSaaS Appliance usage on the following virtualization environments:
-
-* Amazon Web Services (AWS);
-* Microsoft Azure;
-* VMware.
+You may deploy the PSaaS Appliance on your premises using your own infrastructure or the infrastructure of a cloud provider. Currently, Auth0 supports PSaaS Appliance usage on Amazon Web Services (AWS).
## Virtual Machine Templates
@@ -19,8 +23,8 @@ Auth0 provides the PSaaS Appliance via a Virtual Machine Template for you to pro
When provisioning the PSaaS Appliance from the templates, Auth0 recommends the following specifications for the Virtual Machine infrastructure. For multi-node clusters, each node requires a separate VM that meet the specifications.
-* **Memory**: 32 GB RAM (16 GB RAM minimum);
-* **CPU**: 8 vCPU (4 vCPU minimum);
+* **Memory**: 32 GB RAM (minimum);
+* **CPU**: 8 vCPU (minimum);
* **Storage**:
* *For Non-Production Nodes*: 4 drives: 60 GB for system/operating system storage, 50 GB for data storage, 50 GB for User Search, and 50 GB for backup purposes (if you want to test the backup process).
* *For three-node, high availability Production clusters*:
@@ -37,7 +41,7 @@ For multi-node clusters, Auth0 recommends deploying the PSaaS Appliance virtual
## For AWS Users
-* The *recommended* [instance type](https://aws.amazon.com/ec2/instance-types/) is **M4.2xlarge** (M4.xlarge minimum).
+* The *recommended* [instance type](https://aws.amazon.com/ec2/instance-types/) is **m5.2xlarge** (minimum).
* Auth0 will need the following pieces of information to share the AMI with you:
* AWS account number;
* AWS region name. The region should have at least three [availability zones](https://aws.amazon.com/about-aws/global-infrastructure) for your Production cluster.
diff --git a/articles/appliance/instrumentation.md b/articles/appliance/instrumentation.md
new file mode 100644
index 0000000000..1aea21eb0a
--- /dev/null
+++ b/articles/appliance/instrumentation.md
@@ -0,0 +1,61 @@
+---
+section: appliance
+description: This document covers why and how to enable instrumentation in the PSaaS Appliance.
+topics:
+ - appliance
+ - instrumentation
+contentType:
+ - how-to
+useCase: appliance
+applianceId: appliance45
+sitemap: false
+---
+# PSaaS Appliance Monitoring: Instrumentation
+
+The PSaaS Appliance allows you to collect time series data about individual processes and the overall cluster.
+
+To collect and analyze time series data, you must:
+
+* Have instrumentation enabled (please contact Auth0 for assistance with this)
+* Export the data collected to DataDog
+
+If you've chosen to host the PSaaS Appliance in your on-premise data center or in a cloud data center to which you've subscribed (e.g. AWS or Azure), you must use the instrumentation feature to monitor your PSaaS Appliance.
+
+If Auth0 hosts the PSaaS Appliance on your behalf, you do not have access to this feature – Auth0's Managed Service Engineering (MSE) team will use instrumentation to monitor the PSaaS Appliance for you.
+
+## Alerts
+
+The PSaaS Appliance does not come with any built-in tool for sending alerts. To remedy this, we rely on DataDog and Telegraf to help implement robust monitoring and alerting strategies for the PSaaS Appliance.
+
+### Signals to Monitor
+
+These are the signals that the PSaaS Appliance makes available to DataDog via the Telegraf agent. The Telegraf agent defines these signals automatically.
+
+* [CPU](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/CPU_README.md)
+* [Disk](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/DISK_README.md)
+* [Disk IO](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/DISK_README.md)
+* [Memory](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/MEM_README.md)
+* [Processes](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/PROCESSES_README.md)
+* [Swap](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/MEM_README.md)
+* [System](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/SYSTEM_README.md)
+* [MongoDB](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/mongodb/README.md)
+* [Net](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/system/net.go)
+* [NGINX](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/nginx/README.md)
+* [RabbitMQ](https://github.com/influxdata/telegraf/tree/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/rabbitmq)
+* [Procstat](https://github.com/influxdata/telegraf/blob/34b7a4c3611d1ede908ef275401544c34a4a3ba3/plugins/inputs/procstat/README.md)
+* [X509](https://github.com/influxdata/telegraf/blob/release-1.11/plugins/inputs/x509_cert/README.md)
+
+### Auth0 Signals to Monitor
+
+Please note that Auth0 exposes many internal metrics that will be visible in your DataDog console. The names of these metrics typically begin with `auth0_`.
+
+The internal metrics may change at any point, so in most cases, we do not recommend that you build monitoring strategies based on these signals (you can safely ignore these metrics, if you'd like). However, there are a few that you **should** monitor. We list the exceptions in the table below.
+
+| Signal | Description |
+| - | - |
+| auth0_http_requests_received | The total number of requests received by the PSaaS Appliance. |
+| auth0_http_requests_replied | The total number of requests replied to by the PSaaS Appliance. |
+| auth0_http_response_time.count | The number of responses issued by the PSaaS Appliance. This metric corresponds to `auth0_http_requests_replied`. |
+| auth0_http_response_time.lower | The shortest amount of time it took for the PSaaS Appliance to respond to a request. |
+| auth0_http_response_time.mean | The average time it took for the PSaaS Appliance to respond to a request. |
+| auth0_http_response_time.upper | The longest amount of time it took for the PSaaS Appliance to respond to a request. |
diff --git a/articles/appliance/instrumentation/add-grafana-users.md b/articles/appliance/instrumentation/add-grafana-users.md
deleted file mode 100644
index 036bb40a0d..0000000000
--- a/articles/appliance/instrumentation/add-grafana-users.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-section: appliance
-description: This document covers how to add new users to Grafana.
----
-
-# PSaaS Appliance: Adding Users to Grafana
-
-
-By default, each Grafana instance (every PSaaS Appliance node comes with its own instance of Grafana) includes the following users:
-
-* `admin`
-* `root@auth0.com`
-
-To visualize the instrumentation page with an PSaaS Appliance administrative user *other* than `root@auth0.com`, you will need to add that user to the Grafana instances for **each** PSaaS Appliance node.
-
-1. Navigate to the PSaaS Appliance node's instance of Grafana (`https://.com/grafana/`), and log in using a set of valid credentials.
-2. Click the **Grafana icon** located in the top left corner. Select **Admin** and then **Global Users**.
-
- 
-
-3. To add the user, click **+ Add new user**.
-
- 
-
-3. Add the user's *email address* to the **Name**, **Email**, and **Username** fields, and set the user's password. This can be any complex password of the user's choosing. Note that the user will have to enter their password only if they try to access Grafana using Basic Authentication. If the user logs in using OAuth, Grafana will select the user based on the provided email address.
-
- 
-
- You can use one of two authentication methods with Grafana:
-
- ::: panel Grafana Authentication
- * **Basic Authentication**: used by configuration scripts launched by Puppet
- * **OAuth Authentication**: used by when pages when users either:
- * Visualize the instrumentation page;
- * Navigate to Grafana's website.
- :::
-
-4. Click **Create**. You will now see the user reflected in the *Users* list.
-
- 
diff --git a/articles/appliance/instrumentation/available-metrics.md b/articles/appliance/instrumentation/available-metrics.md
deleted file mode 100644
index 3315b0d908..0000000000
--- a/articles/appliance/instrumentation/available-metrics.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-section: appliance
-description: This document covers the metrics available when using Instrumentation.
----
-
-# PSaaS Appliance: Metrics Available via Instrumentation
-
-The following metrics are available to you when Instrumentation is enabled on your PSaaS Appliance:
-
-## Metrics Regarding PSaaS Appliance Infrastructure
-
-* [CPU](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/CPU_README.md)
-* [Disk](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/DISK_README.md)
-* [Disk I/O](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/DISK_README.md)
-* [Memory](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/MEM_README.md)
-* [Processes](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/PROCESSES_README.md)
-* [Swap](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/MEM_README.md)
-* [System](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/SYSTEM_README.md)
-* [MongoDB](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/mongodb/README.md)
-* [Net](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/system/net.go)
-* [NGINX](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/nginx/README.md)
-* [RabbitMQ](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/rabbitmq)
-* [Procstat](https://github.com/influxdata/telegraf/blob/master/plugins/inputs/procstat/README.md)
-
-## Metrics Regarding PSaaS Appliance Processes
-
-* auth0-api2_http_requests_authenticated
-* auth0-api2_http_requests_received
-* auth0-api2_http_requests_replied
-* auth0-api2_http_response_time
-* auth0-import-users-worker_event-loop_blocked
-* auth0-import-users-worker_resources_cpu_usage
-* auth0-import-users-worker_resources_memory_heapTotal
-* auth0-import-users-worker_resources_memory_heapUsed
-* auth0-import-users-worker_resources_memory_usage
-* auth0-notifications_event-loop_blocked
-* auth0-notifications_resources_cpu_usage
-* auth0-notifications_resources_memory_heapTotal
-* auth0-notifications_resources_memory_heapUsed
-* auth0-notifications_resources_memory_usage
-* auth0-server_auth_step_time
-* auth0-server_clients_findByTenantAndClientId
-* auth0-server_connections_getByName
-* auth0-server_http_requests_received
-* auth0-server_http_requests_replied
-* auth0-server_http_response_time
-* auth0-server_tenants_get
-* auth0-users_bootup_time
-* auth0-users_http_requests_received
-* auth0-users_http_requests_replied
-* auth0-users_http_requests_size
-* auth0-users_http_response_time
diff --git a/articles/appliance/instrumentation/components.md b/articles/appliance/instrumentation/components.md
deleted file mode 100644
index 4762ae3b9f..0000000000
--- a/articles/appliance/instrumentation/components.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-section: appliance
-description: This document covers the software used for Instrumentation.
----
-
-# PSaaS Appliance: Instrumentation Components
-
-The following applications are used to implement Instrumentation within the PSaaS Appliance:
-
-* [Grafana](http://grafana.org/): tools for time series and metrics visualization
-* [InfluxDB](https://www.influxdata.com/time-series-platform/influxdb/): time series database used to store/query collected data
-* [Telegraf](https://www.influxdata.com/time-series-platform/telegraf/): tools for gathering data from the PSaaS Appliance
diff --git a/articles/appliance/instrumentation/index.md b/articles/appliance/instrumentation/index.md
deleted file mode 100644
index 822d009713..0000000000
--- a/articles/appliance/instrumentation/index.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-url: /appliance/instrumentation
-section: appliance
-description: This document covers why and how to enable instrumentation in the PSaaS Appliance.
----
-
-# Private SaaS (PSaaS) Appliance: Instrumentation
-
-The PSaaS Appliance ships with a feature called Instrumentation, which makes it easy for your PSaaS Appliance administrators or Auth0 Customer Success Engineers to gather information about the current (or previous) state of the PSaaS Appliance. With Instrumentation, you are collecting time series data about the overall PSaaS Appliance, as well as individual processes. You can then query or visualize this data to draw conclusions about the state of your PSaaS Appliance.
-
-::: note
-Please contact your Auth0 Customer Success Manager if you would like to enable Instrumentation for your PSaaS Appliance (please note that this feature is not available for PSaaS Appliances hosted by Auth0).
-:::
-
-* [Software Components Utilized](/appliance/instrumentation/components)
-* [Available Metrics](/appliance/instrumentation/available-metrics)
-* [Access Your Data](/appliance/instrumentation/access-data)
-* [Visualize Your Data](/appliance/instrumentation/visualize-data)
-* [Add Users in Grafana](/appliance/instrumentation/add-grafana-users)
diff --git a/articles/appliance/instrumentation/visualize-data.md b/articles/appliance/instrumentation/visualize-data.md
deleted file mode 100644
index d4ed8da02a..0000000000
--- a/articles/appliance/instrumentation/visualize-data.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-section: appliance
-description: This document covers how to visualize data gathered via Instrumentation.
----
-
-# PSaaS Appliance: How to Visualize Your Data
-
-Once you have enabled Instrumentation, you can access your data in one of two places:
-
-* PSaaS Appliance Dashboard
-* Grafana
-
-## View Your Data in the PSaaS Appliance Dashboard
-
-If you would like to see your data in the Appliance Dashboard, navigate to `https:///configuration#/instrumentation` to access the graphs created from the data collected from your PSaaS Appliance instances.
-
-
-
-## Access Your Data Directly from Grafana
-
-Each PSaaS Appliance node has its own instances of Grafana, InfluxDB, and Telegraph. To access a given node's Grafana instance:
-
-1. Obtain the node's private IP address
-2. Using the private IP address, navigate to `https://.com/grafana/`
-
-### Add Grafana Dashboards to the Instrumentation Page in the PSaaS Appliance Dashboard
-
-If you need to view relationships between datasets that have yet to be graphed, you can create new (or update existing) Grafana Dashboards displayed on the PSaaS Appliance Dashboard's Instrumentation page. To create new Grafana dashboards, please view [this video](https://www.youtube.com/watch?v=sKNZMtoSHN4&index=7&list=PLDGkOdUX1Ujo3wHw9-z5Vo12YLqXRjzg2).
-
-Once you have created your Grafana dashboards, tag them as `instrumentation` so that they appear on the Instrumentation page. To do this:
-
-1. Navigate to the Grafana dashboard's *Settings > General* page.
-2. Add a tag to the appropriate Grafana dashboard called `instrumentation`.
-
-
diff --git a/articles/appliance/modules.md b/articles/appliance/modules.md
index 7c3b86f186..494289c92f 100644
--- a/articles/appliance/modules.md
+++ b/articles/appliance/modules.md
@@ -1,48 +1,49 @@
---
section: appliance
description: For security reasons, rules and custom database connections for PSaaS Appliance run in a JavaScript sandbox. You can use the full power of the ECMAScript 5 language and a few selected libraries.
+topics:
+ - appliance
+ - js-modules
+ - sandbox
+contentType: reference
+useCase: appliance
+applianceId: appliance60
+sitemap: false
---
# Node.js Modules Available in Rules and Custom Database Connections
-For security reasons, rules and custom database connections for PSaaS Appliance run in a JavaScript sandbox. You can use the full power of the ECMAScript 5 language and a few selected libraries.
-
-The latest version of the PSaaS Appliance supports the use of three different modes:
-* Webtask - This model has the same functionality as the Auth0 cloud version. It provides a balance between performance and isolation, supports a greater number of node modules, and is the recommended model for most customers;
-* In process - This model executes within the Node.js process of the Auth0 service. This provides the best raw performance. The model provides no isolation between custom code and the Auth0 service, and supports only the limited set of modules listed below. The recommended approach for high scale is to allocate additional resources and use the Webtask model. In some very demanding conditions where isolation is not a concern, this model may be considered;
-* Out-of-process - This is the original model that provides high isolation. It has significantly higher performance overhead compared to the other two models and supports the limited set of modules listed below.
+For security reasons, you must execute rules and custom database logic for PSaaS Appliance using [the Webtask stage/sandbox](/appliance/webtasks). The sandbox offers you a performant environment running ECMAScript 6 and provides isolation for the code you've written.
The current sandbox supports:
-* [async](https://github.com/caolan/async) _(~0.9.0)_
-* [auth0](https://github.com/auth0/node-auth0) _(2.0.0-alpha.5)_
-* [azure_storage](https://github.com/Azure/azure-storage-node) _(~0.4.1)_
-* [bcrypt](https://github.com/ncb000gt/node.bcrypt.js) _(~0.8.3)_
-* [Buffer](http://nodejs.org/docs/v0.10.24/api/buffer.html)
-* [couchbase](https://github.com/couchbase/couchnode) _(~1.2.1)_
-* [cql](https://github.com/jorgebay/node-cassandra-cql) _(~0.4.4)_
-* [crypto](http://nodejs.org/docs/v0.10.24/api/crypto.html)
-* [ip](https://github.com/keverw/range_check) _(0.0.1)_
-* [jwt](https://github.com/auth0/node-jsonwebtoken) _(~0.4.1)_
-* [knex](http://knexjs.org) _(~0.6.3)_
- * The function returned by `require('knex')` is available as `Knex`.
-* [lodash](https://github.com/lodash/lodash) _(~2.4.1)_
-* [mongo](https://github.com/mongodb/node-mongodb-native) _(~1.3.15)_
- * [BSON](http://mongodb.github.io/node-mongodb-native/api-bson-generated/bson.html)
- * [Double](http://mongodb.github.io/node-mongodb-native/api-bson-generated/double.html)
- * [Long](http://mongodb.github.io/node-mongodb-native/api-bson-generated/long.html)
- * [ObjectID](http://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html)
- * [Timestamp](http://mongodb.github.io/node-mongodb-native/api-bson-generated/timestamp.html)
-* [mysql](https://github.com/felixge/node-mysql) _(~2.0.0-alpha8)_
-* [pbkdf2](https://github.com/davidmurdoch/easy-pbkdf2) _(0.0.2)_
-* [pg](https://github.com/brianc/node-postgres) _(4.1.1)_
-* [pubnub](https://github.com/pubnub/javascript/tree/master/node.js) _(3.7.0)_
-* [q](https://github.com/kriskowal/q) _(~1.0.1)_
-* [querystring](http://nodejs.org/api/querystring.html) _(0.10.28)_
-* [request](https://github.com/mikeal/request) _(~2.27.0)_
-* [sqlserver](https://github.com/pekim/tedious) _(~0.1.4)_
-* [uuid](https://github.com/broofa/node-uuid) _(~2.0.1)_
-* [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js) _(~0.2.8)_
-* [xmldom](https://github.com/jindw/xmldom) _(~0.1.13)_
-* [xpath](https://github.com/goto100/xpath) _(0.0.5)_
-* [xtend](https://github.com/Raynos/xtend) _(~1.0.3)_
+| Module | Version (If Applicable) | Notes |
+| - | - | - |
+| [async](https://github.com/caolan/async) | ~2.1.2 | |
+| [auth0](https://github.com/auth0/node-auth0) | 2.13.0 | 2.13.0 |
+| [bcrypt](https://github.com/ncb000gt/node.bcrypt.js) | ~3.0.0 | |
+| [Buffer](http://nodejs.org/docs/v0.10.24/api/buffer.html) | | |
+| [cql](https://github.com/jorgebay/node-cassandra-cql) | ~0.4.4 | |
+| [crypto](http://nodejs.org/docs/v0.10.24/api/crypto.html) | | |
+| [ip](https://github.com/keverw/range_check) | 0.3.2 | |
+| [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) | ~7.1.9 | |
+| [knex](http://knexjs.org) | ~0.8.6 | The function returned by `require('knex')` is available as `Knex`. |
+| [lodash](https://github.com/lodash/lodash) | ~4.17.10 | |
+| [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) | ~2.0.33 | |
+| [node-mongodb-native - BSON](http://mongodb.github.io/node-mongodb-native/api-bson-generated/bson.html) | 0.3.2 | |
+| [node-mongodb-native - Double](http://mongodb.github.io/node-mongodb-native/api-bson-generated/double.html) | | |
+| [node-mongodb-native - Long](http://mongodb.github.io/node-mongodb-native/api-bson-generated/long.html) | | |
+| [node-mongodb-native - ObjectID](http://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html) | | |
+| [node-mongodb-native - Timestamp](http://mongodb.github.io/node-mongodb-native/api-bson-generated/timestamp.html) | | |
+| [mysql](https://github.com/felixge/node-mysql) | ~2.15.0 | |
+| [pbkdf2](https://github.com/davidmurdoch/easy-pbkdf2) | 0.0.2 | |
+| [pg](https://github.com/brianc/node-postgres) | 6.1.2 | |
+| [pubnub](https://github.com/pubnub) | 3.7.11 | |
+| [q](https://github.com/kriskowal/q) | ~1.4.1 | |
+| [querystring](http://nodejs.org/api/querystring.html) | 0.2.0 | |
+| [request](https://github.com/mikeal/request) | ~2.81.0 | |
+| [uuid](https://github.com/kelektiv/node-uuid) | ~3.3.2 | |
+| [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js) | ~0.11.2 | |
+| [xmldom](https://github.com/jindw/xmldom) | ~0.1.13 | |
+| [xpath](https://github.com/goto100/xpath) | 0.0.9 | |
+| [xtend](https://github.com/Raynos/xtend) | ~4.0.0 | |
diff --git a/articles/appliance/monitoring/authenticated-endpoints.md b/articles/appliance/monitoring/authenticated-endpoints.md
index 5a956f236a..50fa8bc069 100644
--- a/articles/appliance/monitoring/authenticated-endpoints.md
+++ b/articles/appliance/monitoring/authenticated-endpoints.md
@@ -1,69 +1,171 @@
---
section: appliance
description: Overview of using the authenticated endpoint with the PSaaS Appliance
+topics:
+ - appliance
+ - monitoring
+ - testing
+contentType: how-to
+useCase: appliance
+applianceId: appliance47
+sitemap: false
---
-# PSaaS Appliance: Using Authenticated Testing Endpoints
+# PSaaS Appliance: Authenticated Testing Endpoints
-For calls to the testing endpoints that return detailed information, Auth0 requires these requests to be authenticated using a key generated using the PSaaS Appliance Dashboard. This key is used in the request header of the call sent to the endpoint.
+Auth0 offers endpoints that allow you to check the system health of a specific resource. In this article, we will cover the authenticated endpoints, which are available to those who submit requests whose header contains the appropriate credentials.
-## Generating the API Key
+The authenticated endpoints are similar to the Test All endpoints in that both return positive or negative status information about system resources.
-To generate an API Key for use the authenticated testing endpoints, navigate to the [Settings](/appliance/dashboard/settings) page of your PSaaS Appliance Dashboard. There, you will find an [API Keys section](/appliance/dashboard/settings#api-keys) that allows you to generate new keys.
+Authenticated endpoints do not provide detailed information about the system's resource utilization. Instead, they return an HTTP status reflecting the status of a given resource. Using the third-party tools of your choice, you can set up alerts that activate based on the status codes returned by Auth0's endpoints.
-During the first use, you will see a that there is no key. To generate your first key, click on the "Generate" button at the far right of the row.
+## How to generate an API key
+
+To send requests to the authenticated endpoints, you will need to generate and include an API key in the header of your request.
+
+Begin by navigating to the [Settings](/appliance/dashboard/settings) page of your PSaaS Appliance Dashboard. Scroll down to the [API Keys section](/appliance/dashboard/settings#api-keys).
+
+If this is the first time you are doing this, you'll see that there is no key. You can generate your first key by clicking the **Generate** button to the right.

-You will be prompted to confirm the new key generation. If confirmed, you will see that the key now populates the previously-blank field.
+You will be prompted to confirm the new key generation.
+
+Once confirmed, you will see that the key now populates the previously-blank field.

+Scroll to the bottom of the page, and click Save to apply the new API Key value.
+
+At this point, Auth0 does a reconfiguration and restarts the health service. Once this process completes, you will be able to use your new API key.
+
:::panel-warning Changing Your API Key
-You may only use one key at a time. If you generate a new key, all applications and services using the old key will fail.
+You may only use one API key at a time. If you generate a new key, be sure to provide the new key to your existing applications and services; otherwise, they will fail.
:::
-## Available Endpoints
+## Authenticated API Endpoints
+
+The API exposes a number of endpoints that you can use to test the status of the service.
-The following authenticated endpoints are available for you to use:
+**Each node comes with its own set of endpoints, so you will need to make multiple calls if you are monitoring a multi-node PSaaS Appliance implementation.** The exception is the `GET /status/replicaset` endpoint, which reports on multiple nodes.
-* GET /status/cpu
-* GET /status/memory
-* GET /status/disk
-* GET /status/services
-* GET /status/network
-* GET /status/internet
-* GET /status/email
-* GET /status/db
-* GET /status/replicaset
+There are two ways you can call a specific API endpoint:
-Your call might look something like the following:
+* Submit your request to the node directly
+* Issue your request through the load balancer using the manage domain
+
+If you're checking the status of a specific node, it's best to submit your request to the node directly:
```text
-curl -v http://127.0.0.1:9110/status/cpu
---user api_keys_health:YOUR_API_KEY
+curl -v https://{node-ip}/health/status/cpu --user api_keys_health:YOUR_API_KEY
```
-You may also make the call via https, though you will have to make the following modifications to your call:
- * Add "health" to the URL path;
- * Remove the port number from the IP address used.
+Otherwise, you can issue your request through the load balancer using the **manage** domain:
+
+```text
+curl -v https://{manage-dashboard-domain}/health/status/cpu --user api_keys_health:YOUR_API_KEY
+```
+
+### Response Codes
+
+Each endpoint will return one of three status codes to communicate the status of the resource in question:
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | OK |
+| 429 | Too many requests |
+| 520 | Warning |
+
+Additionally, each status code conveys additional information depending on the endpoint being queried. You'll find more information on this in the following sections that cover the specific endpoints available to you.
+
+None of the responses will include a body.
+
+#### GET /status/cpu
+
+This endpoint returns information about the overall available CPU capacity in the last minute on the PSaaS Appliance. Overall CPU capacity means that all CPU time is aggregated and compared with the time that any core was not idle. For example, if a four-core PSaaS Appliance node had two cores completely utilized and two cores completely idle, the CPU capacity calculated will be 50%.
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | The system had more than 20% of the total CPU capacity available in the last minute. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | The system had 20% of the total CPU capacity (or less) available in the last minute. |
+
+#### GET /status/memory
+
+This endpoint returns information on the amount of memory available on the PSaaS Appliance.
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | The system has more than 10% of its memory available. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | The system has 10% (or less) of its memory available. |
+
+#### GET /status/disk
+
+This endpoint returns information on disk utilization. Each node has a set number of volumes; if there is at least one volume that's utilizing more than 90% of the allocated disk space, the endpoint returns a warning.
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | No volume on the node exceeds 90% utilization. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | One or more disk(s) on the node has exceeded 90% utilization. |
+
+#### GET /status/services
-For example, `http://10.1.0.248:9110/status/cpu` becomes `https://10.1.0.248/health/status/cpu`.
+This endpoint checks to see if any of the node's core Auth0 services are down.
-## Access from Outside the PSaaS Appliance
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | Every core service is running on the node. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | At least one of the core services on the node is not running. |
+
+#### GET /status/network
+
+This endpoint reports the status of the network for the node. The node issues a PING command to each node in the cluster, and if it fails to PING any node, the endpoint will return an error code.
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | The node was able to successfully ping every other node in the cluster. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | The node was not able to ping at least one node in the cluster, indicating there's a network problem. |
-If you'd like to access these endpoints from outside the PSaaS Appliance, you can do so using your `manage` domain.
+#### GET /status/internet
-| Internal Access | External Access |
-| --------------- | --------------- |
-| http://10.1.0.248:9110/status/cpu **or** https://10.1.0.248/health/status/cpu | ${manage_url}/health/status/cpu |
+This endpoint tests outbound internet connectivity on the node over port 443. This endpoint issues a `HEAD` request to `https://apt-mirror.it.auth0.com`. If the request returns anything other than a 200 status code, this endpoint will return an HTTP code indicating failure.
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | The node was able to successful issue a `HEAD` request to `https://apt-mirror.it.auth0.com`. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | The was unable to issue a `HEAD` request, or the node received an error message after sending a `HEAD` request to `https://apt-mirror.it.auth0.com`. |
+
+#### GET /status/email
+
+This endpoint tests the SMTP connection using the provided configuration settings.
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | The node was able to use the provided configuration settings to connect to the SMTP server. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | The node was unable to connect to the SMTP server. |
+
+#### GET /status/db
+
+This endpoint checks to see if the node can run database queries and receive the results.
+
+| Response Code | Response |
+| ------------- | -------- |
+| 204 | The node was able to successfully query the database. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | The node was not able to connect and run a query against the database. |
-## Endpoint Responses
+#### GET /status/replicaset
-Calls to authenticated endpoints will return in one of the following status codes:
+This endpoint checks to see if the replica set is healthy. If there is at least one node that is down, the endpoint will return an HTTP code indicating failure.
| Response Code | Response |
| ------------- | -------- |
-| 204 | There are no issues with the resource. |
-| 429 | Too many requests have been made to the resource. |
-| 520 | There is an issue with the resource. |
+| 204 | All nodes in the replica set are up. |
+| 429 | The status endpoint has been called too many times (limit: 10 requests per second). Please wait and try again. |
+| 520 | At least one node in the replica set is down. |
diff --git a/articles/appliance/monitoring/index.md b/articles/appliance/monitoring/index.md
index 3d3fc5937f..a7f8f588d9 100644
--- a/articles/appliance/monitoring/index.md
+++ b/articles/appliance/monitoring/index.md
@@ -2,17 +2,76 @@
url: /appliance/monitoring
section: appliance
description: Ways to monitor the PSaaS Appliance
+topics:
+ - appliance
+ - monitoring
+contentType:
+- index
+- concept
+useCase: appliance
+applianceId: appliance48
+sitemap: false
---
# Monitoring the Private SaaS (PSaaS) Appliance
-In addition to providing tools for monitoring your PSaaS Appliance, Auth0 provides integration with select third-party utilities.
+The PSaaS Appliance is a managed service, which means that Auth0 is responsible for:
-Your options include:
+* Installation
+* Updates
+* General maintenance tasks
-* **Instrumentation**: If [Instrumentation](/appliance/instrumentation) has been enabled for your PSaaS Appliance instances, you can gather and visualize data about your infrastructure and processes
- * If you've enabled Instrumentation, you can send your data to DataDog. You'll need to supply your DataDog API key in the configuration page to do this. When viewing your metrics in DataDog, it will *not* appear in the standard DataDog UI under Infrastructure. You'll need to add your own dashboard and search for the PSaaS Appliance data you want displayed.
-* **Health Checks**: [Health Checks](/appliance/dashboard/troubleshoot#health-check) provide minute-by-minute summaries of your PSaaS Appliance infrastructure at a given point in time. These logs are available for the the previous twenty-nine days and can be found in the [Troubleshoot](/appliance/dashboard/troubleshoot) page of your PSaaS Appliance Configuration Area;
-* **[Auth0's `testall` Endpoint](/appliance/monitoring/testall)**: The `testall` endpoint is an unauthenticated endpoint that is particularly useful for monitoring by load balancers;
-* **[Auth0's Authenticated Testing Endpoints](/appliance/monitoring/authenticated-endpoints)**: Auth0 provides endpoints that you may, once authenticated, call to receive status codes such as *204*, *520*, or *429*;
-* **Integration with Third-Party Utilities to Monitor Synthetic Transactions**: Auth0 supports integration with system monitoring tools like *Microsoft System Center* so that you can [run and monitor synthetic transactions](/monitoring#configuring-scom).
\ No newline at end of file
+However, the deployment option you choose affects the scope of what Auth0 can do when it comes to *monitoring* the PSaaS Appliance. Currently, Auth0 supports the following deployment options:
+
+* The subscriber's Amazon Web Services cloud environment
+* An Auth0-controlled data center
+
+If you choose to deploy the PSaaS Appliance to an Auth0-controlled data center, we have control over every aspect involved (DNS, certificates, infrastructure, Auth0 software stack). This level of control allows us to assist you in monitoring the health of the PSaaS Appliance and acting to prevent or remediate issues.
+
+However, if you choose to deploy the PSaaS Appliance to AWS, **you are responsible for monitoring the deployment. Auth0 is unable to monitor such environments.**
+
+::: note
+Please review [PSaaS Appliance: Roles and Responsibilities](https://auth0.com/docs/appliance/raci) for information on who is responsible for various activities related to managing and monitoring the PSaaS Appliance.
+:::
+
+## Features Aiding Monitoring
+
+The PSaaS Appliance offers a number of tools to help you monitor the software that is running, as well as the infrastructure on which it runs. You can find additional information on these monitoring tools in the chart that follows:
+
+| Tool | Description |
+| - | - |
+| Service Status Check | The [`/testall` endpoint](/appliance/monitoring/testall) reports the overall status of core Auth0 services. You can call this endpoint from the load balancer or from an individual node. If called from the load balancer, you can determine if there's a system-wide service outage. If called from a specific node, you'll receive information on the status of core services running on that node alone. |
+| System Health Checks | The [authenticated endpoints](/appliance/monitoring/authenticated-endpoints) provide a more granular health check than the `/testall` endpoint, allowing you to see the status of lower level system resources. With these endpoints, you can monitor the status of the PSaaS Appliance as it relates to memory, disk, network, internet, email, database, replica set, services, and the cluster.
The authenticated endpoints return status codes indicating whether the system resource in question is healthy or not. |
+| [Instrumentation](/appliance/instrumentation) | The PSaaS Appliance offers instrumentation data, which is a vital component of monitoring and detecting anomalies or problems *before* they occur. To review your PSaaS Appliance instrumentation data, you can send it to DataDog. With DataDog, you can set up robust monitoring and alerts strategies to review the health of your PSaaS Appliance. |
+| Dashboards | The PSaaS Appliance's [Troubleshooting](/appliance/dashboard/troubleshoot) dashboard allows you to view [Health Check](/appliance/dashboard/troubleshoot#health-check) results for the past 29 days. Please note that this dashboard does not provide any alerts functionality and should not be used as your only monitoring strategy. |
+| Audit and Tenant Events | The [Tenant Logs](https://auth0.com/docs/logs) track processed transactions and provide an overview of application activity in your tenant. |
+| Synthetic Transactions | You can use any third-party service that supports synthetic transaction to monitor PSaaS Appliance service availability. |
+
+## Recommended Monitoring Strategy
+
+Because each subscriber's implementation is different, the monitoring strategy you employ should match the needs of your use case.
+
+With that said, Auth0 suggests the following as a starting point for monitoring the PSaaS Appliance. The signals mentioned are indicators that there might be an unhealthy scenario occurring and provide information on the appropriate action for you to take:
+
+| Signal | Trigger | Action |
+| - | - | - |
+| [/testall at load balancer level](/appliance/monitoring/testall) | Does not return 200 with body OK | [Submit a support ticket](/support/tickets) with a severity of **Urgent** |
+| [/testall at node level](/appliance/monitoring/testall#monitoring-individual-nodes) | Does not return 200 with body OK | [Submit a support ticket](/support/tickets) with a severity of **High** |
+| [GET /status/memory](/appliance/monitoring/authenticated-endpoints#get-status-memory) at node level | Returns a 520 status code | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+| [GET /status/disk](/appliance/monitoring/authenticated-endpoints#get-status-disk) at node level | Returns a 520 status code | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+| [GET /status/network](/appliance/monitoring/authenticated-endpoints#get-status-network) at node level | Returns a 520 status code | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+| [GET /status/internet](/appliance/monitoring/authenticated-endpoints#get-status-internet) at node level | Returns a 520 status code | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+| [GET /status/email](/appliance/monitoring/authenticated-endpoints#get-status-email) at node level | Returns a 520 status code | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+| [GET /status/db](/appliance/monitoring/authenticated-endpoints#get-status-db) at node level | Returns a 520 status code | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+| [GET /status/replicaset](/appliance/monitoring/authenticated-endpoints#get-status-replicaset) at node level | Returns a 520 status code | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+| Synthetic Transaction: Login | Synthetic login failed | [Submit a support ticket](/support/tickets) with a severity of **Normal** |
+
+When building your monitoring strategy for a PSaaS Appliance implementation hosted on an environment you own or control, remember that you are responsible for using the instrumentation and tenant log data to watch for anomalies.
+
+## Your Responsibilities in Monitoring the Auth0-Hosted PSaaS Appliance
+
+If Auth0 hosts your PSaaS Appliance, you won't have access to instrumentation data. However, you are still expected to monitor your tenant logs for anomalies, since this provides you information on the health of your PSaaS Appliance-dependent applications.
+
+If Auth0 hosts your PSaaS Appliance implementation, Auth0's Managed Service Engineering (MSE) team is responsible for monitoring. However, the MSE team is focused on the health of the PSaaS Appliance – you are responsible for tracking the health of your applications, as well as its usage of Auth0.
+
+If you provide Auth0 with the appropriate email addresses, Auth0 can send a daily uptime report of your hosted PSaaS Appliance service to those email addresses. You can also specify one or more email addresses to which Auth0 will send alerts in the event that there is an issue.
diff --git a/articles/appliance/monitoring/testall.md b/articles/appliance/monitoring/testall.md
index e3e3b76298..442f42ee39 100644
--- a/articles/appliance/monitoring/testall.md
+++ b/articles/appliance/monitoring/testall.md
@@ -1,6 +1,14 @@
---
section: appliance
description: Overview of using the testall endpoint with the PSaaS Appliance
+topics:
+ - appliance
+ - monitoring
+ - testing
+contentType: how-to
+useCase: appliance
+applianceId: appliance49
+sitemap: false
---
# Using the `testall` Endpoint
@@ -25,9 +33,11 @@ Alternatively, if there are any issues, `/testall` returns a `5xx` response code
Typically, the above endpoint will reach the load balancer, but since a typical, highly-available deployment will have at least three nodes, Auth0 recommends monitoring those endpoints as well:
-* `https://{IP Address Node 1}/testall`
-* `https://{IP Address Node 2}/testall`
-* `https://{IP Address Node 3}/testall`
+* `http://{IP Address Node 1}/testall`
+* `http://{IP Address Node 2}/testall`
+* `http://{IP Address Node 3}/testall`
+
+Be sure to use the `http` *not* `https` in your URLs.
### Non-Responsive Nodes
diff --git a/articles/appliance/private-cloud-requirements.md b/articles/appliance/private-cloud-requirements.md
index 3814ccf858..58a4f080df 100644
--- a/articles/appliance/private-cloud-requirements.md
+++ b/articles/appliance/private-cloud-requirements.md
@@ -2,6 +2,14 @@
section: appliance
description: This document details the requirements for the Auth0 Dedicated Cloud Service.
toc: true
+topics:
+ - appliance
+ - private-cloud
+ - requirements
+contentType: reference
+useCase: appliance
+applianceId: appliance61
+sitemap: false
---
# Requirements for the Auth0 Dedicated Cloud Service
@@ -70,7 +78,7 @@ The Management Dashboard, Webtask, and App Tenant(s) **must** be a part of the s
The hostname (such as **manage-project**.yourdomain.auth0.com) must be at least three characters long and must **not** contain any underscores(_).
-The word `login` is reserved and **cannot** be used.
+The word `login` is reserved and **cannot** be used. Please also refer to the [full list of reserved words](/appliance/infrastructure/dns#hostnames).
The domain name you use for tenants hosted in the Dedicated Cloud Service **cannot** be the same as any you're using for tenants hosted in the Public Cloud Service.
diff --git a/articles/appliance/raci.md b/articles/appliance/raci.md
index e283148842..4d86c2fe93 100644
--- a/articles/appliance/raci.md
+++ b/articles/appliance/raci.md
@@ -1,6 +1,13 @@
---
section: appliance
description: This document details who is responsible for what aspects of a given PSaaS Appliance installation.
+topics:
+ - appliance
+ - raci
+contentType: reference
+useCase: appliance
+applianceId: appliance62
+sitemap: false
---
# PSaaS Appliance: Roles and Responsibilities
@@ -36,14 +43,14 @@ The following RACI Matrix provides a more in-depth summary of the roles and resp
|PSaaS Appliance-Related Tasks or Deliverables|Auth0|Subscriber|Notes|
|---|---|---|---|
|Preparing VM Infrastructure, including: memory, storage, processors, load balances, networks, SSL certificates, DNS records, SMTP servers, enabling Auth0 access via Jumphost/VPN|C|R, A (subscriber's infrastructure engineer)|The subscriber will submit the PSaaS Appliance Infrastructure Checklist when the VMs are ready and the [infrastructure requirements](/appliance/infrastructure) are met.|
-|Deployment to Development and Production environments|R, A - Auth0 Customer Success Engineer|I|The Auth0 Customer Success Engineer will SSH into the VMs and deploy the Appliance.|
-|Configuration of Development and Production environments|C|R|The Auth0 CSE will show the subscriber's infrastructure engineer [how to upload the SSL certificates, enter the SMTP credentials, and add administrators](/appliance/dashboard).|
-|Operations Handover|R|C|Auth0 Customer Success Engineers will provide a 90-minute Operations Handover meeting to review information regarding PSaaS Appliance monitoring, backup, and updates, as well as answer questions.|
+|Deployment to Development and Production environments|R, A - Auth0 Managed Service Engineer (MSE)|I|The Auth0 Managed Service Engineer will SSH into the VMs and deploy the Appliance.|
+|Configuration of Development and Production environments|C|R|The Auth0 MSE will show the subscriber's infrastructure engineer [how to upload the SSL certificates, enter the SMTP credentials, and add administrators](/appliance/dashboard).|
+|Operations Handover|R|C|Auth0 Managed Service Engineers will provide a 90-minute Operations Handover meeting to review information regarding PSaaS Appliance monitoring, backup, and updates, as well as answer questions.|
|Monitoring|I|R, A|The subscriber is responsible for [monitoring the PSaaS Appliance](/appliance/monitoring).|
|Backing Up|I (in the event that there are issues)|R, A|The subscriber is responsible for [backing up the PSaaS Appliance](/appliance/disaster-recovery) using the [Command-Line Tools](/appliance/cli).|
|Code Integration into Applications|C, I (in the event that there are issues)|R, A|The subscriber is responsible for Auth0 code integration.|
|User Migration (if required)|C, I (in the event that there are issues)|R, A|The subscriber is responsible for migrating users where appropriate.|
-|Updates|R|R, A|Auth0 Customer Success Engineers will partner with the subscriber's infrastructure engineers to update the PSaaS Appliance on an agreed-upon basis. The subscriber is responsible for: taking VM snapshot(s) prior to the update, providing access to the PSaaS Appliance, being present as the PSaaS Appliance updates. Auth0 is responsible for: running manual scripts (if required), informing the subscriber on the status of the upgrade.|
+|Updates|R|R, A|Auth0 Managed Service Engineers will partner with the subscriber's infrastructure engineers to update the PSaaS Appliance on an agreed-upon basis. The subscriber is responsible for: taking VM snapshot(s) prior to the update, providing access to the PSaaS Appliance, being present as the PSaaS Appliance updates. Auth0 is responsible for: running manual scripts (if required), informing the subscriber on the status of the upgrade.|
|Testing Updates|C, I (in the event that there are questions/issues)|R, A|The subscriber will test the PSaaS Appliance after the Development node has been updated and inform Auth0 about any issues.|
|Issue Identification and Support Ticket Submission|C|R, A|The subscriber is responsible for submitting issues via the [Support Center](/onboarding/enterprise-support).|
|Issue Resolution|R|C|Auth0 will provide support for issues within the *core* of the PSaaS Appliance. Auth0 will *consult* on issues pertaining to integration between Auth0 APIs and Dashboards.|
diff --git a/articles/appliance/remote-access-options.md b/articles/appliance/remote-access-options.md
index 6b0e8b96c5..586fd59a1f 100644
--- a/articles/appliance/remote-access-options.md
+++ b/articles/appliance/remote-access-options.md
@@ -1,6 +1,13 @@
---
title: PSaaS Appliance Remote Access Options
description: Remote Access Options Available for those with PSaaS Appliance
+topics:
+ - appliance
+ - remote-access
+contentType: reference
+useCase: appliance
+applianceId: appliance63
+sitemap: false
---
# PSaaS Appliance Remote Access Options
@@ -43,25 +50,7 @@ Similar to option 1, this configuration permits an external Auth0 Jumphost to co
* Additional virtual Jumphost required in customer infrastructure
-### Option 3: VPN
-
-This configuration provides VPN access to the customer’s network either to Auth0 engineers individually or a dedicated, Jumphost-like Auth0 server.
-
-
-
-*Pros*:
-
-* Customers usually have VPN infrastructure in place
-* No additional servers are required
-* Auth0 access can be enabled and disabled using existing VPN account procedures
-
-*Cons*:
-
-* Inability to audit management activity on the command line
-* Customer responsible for provisioning VPN accounts for Auth0 engineers and Identity Management
-* Customer responsible for securing VPN traffic only to PSaaS appliance
-* Customer is responsible for VPN availability (critical to allow access during support events)
### Unsupported Configurations
-We do not support other methods, such as VDI or Screen Sharing mechanisms. They introduce compliance concerns, including (but not limited to) Auth0’s inability to internally audit connections and SSH sessions, enforce identity management on Auth0 employee accounts,exposure to untrusted systems on customer’s end running non-standard software (from where the connections are generated to Auth0 VMs), and inability to verify the identity of participants on the other end.
\ No newline at end of file
+We do not support other methods, such as VDI or Screen Sharing mechanisms. They introduce compliance concerns, including (but not limited to) Auth0’s inability to internally audit connections and SSH sessions, enforce identity management on Auth0 employee accounts, exposure to untrusted systems on customer’s end running non-standard software (from where the connections are generated to Auth0 VMs), and inability to verify the identity of participants on the other end.
diff --git a/articles/appliance/webtasks/dedicated-domains.md b/articles/appliance/webtasks/dedicated-domains.md
index 60008d3540..11bbe60ff3 100644
--- a/articles/appliance/webtasks/dedicated-domains.md
+++ b/articles/appliance/webtasks/dedicated-domains.md
@@ -3,15 +3,24 @@ section: appliance
title: Configure Webtask with Dedicated Domains
description: How to use dedicated domains with your PSaaS Appliance Webtask
toc: true
+topics:
+ - appliance
+ - webtask
+ - domains
+contentType:
+ - concept
+ - reference
+ - how-to
+useCase: appliance
+applianceId: appliance50
+sitemap: false
---
# PSaaS Appliance: Webtask with Dedicated Domains
-Some extensions, such as the [Authorization Extension](/extensions/authorization-extension/v2), required us to enable full trust in your PSaaS environment to run correctly.
-
-Beginning with PSaaS Appliance version `13451`, you may now configure Webtask on a dedicated domain. This enables you to safely use extensions in multi-tenant environments (the behavior is akin to that of the Auth0 Public Cloud Service).
+In order to use extensions, such as the [Authorization Extension](/extensions/authorization-extension/v2), you will need to configure Webtasks on a dedicated domain in PSaaS Appliance environments. This enables you to safely use extensions in multi-tenant environments (the behavior is akin to that of the Auth0 Public Cloud Service).
::: note
-If you do not use Webtask or [Extensions](/appliance/extensions), you do not need to implement Webtask dedicated domains.
+If you are planning on using [Extensions](/appliance/extensions), you must implement Webtask dedicated domains.
:::
## Background
@@ -81,7 +90,7 @@ No. Because the tenant name is used in the first part of the domains for the Aut
**Do I have to enable Webtask Dedicated Domains?**
-Yes, if you are planning to use extensions. If you are not planning on using extensions, you do not have to enable dedicated domains.
+Yes, if you are planning on using Extensions, you must implement Webtask dedicated domains.
**Can the Webtask tenant names differ from the one used by the Auth0 tenant?**
diff --git a/articles/appliance/webtasks/index.md b/articles/appliance/webtasks/index.md
index 7260e6488c..c390c9c027 100644
--- a/articles/appliance/webtasks/index.md
+++ b/articles/appliance/webtasks/index.md
@@ -1,6 +1,15 @@
---
section: appliance
description: How to use Webtasks on the PSaaS Appliance
+topics:
+ - appliance
+ - webtask
+contentType:
+ - concept
+ - index
+useCase: appliance
+applianceId: appliance51
+sitemap: false
---
# PSaaS Appliance: Webtasks
@@ -14,23 +23,7 @@ Prior to working with Webtasks, please ensure that you have configured the:
* [Webtask Command Line Interface (`wt-cli`)](https://webtask.io/docs/101)
:::
-## Sandboxes
-
-Auth0 provides different stages (which are known as sandboxes) on which you may run your rules and custom database logic:
-
-* `node_sandbox` (default): while more secure than `eval`, `node_sandbox` is more resource intensive;
-* `eval`: provides the best performance, but is the least secure of the three available modes;
-* `auth0-sandbox`: provides better performance that `node_sandbox`, improved isolation over `eval`, and offers a greater number of Node.js modules for use with your custom code.
-
-::: note
-Only one sandbox mode may be selected at any given time (for example, you may not run selected rules in one sandbox and other rules in another sandbox). If you would like to change the sandbox mode, please discuss this with your Auth0 Customer Success Engineer.
-:::
-
-## Code Compatibility
-
-Code that you have written for use with `node-sandbox` or `eval` will work in `auth0-sandbox`. However, code that is written for `auth0-sandbox` may not be compatible with `node-sandbox` or `eval`, especially if your code uses modules.
-
-The `auth0-sandbox` is the recommended method for running your custom code.
+Auth0 provides `auth0-sandbox`, a stage (sometimes referred to as a *sandbox*) on which you may run your rules and custom database logic.
## Working with Webtasks
@@ -38,11 +31,13 @@ You may use Webtasks by calling its endpoints directly. This can be done using t
### Node.js Modules
-Currently, not all of the [Node.js modules available for the Auth0 Cloud Environment](https://tehsis.github.io/webtaskio-canirequire/) are available for the PSaaS Appliance.
+Currently, not all of the [Node.js modules available for the Auth0 Cloud Environment](https://auth0-extensions.github.io/canirequire/) are available for the PSaaS Appliance.
-To see which modules are available for Webtasks running on PSaaS Appliance instances, execute the [`List Modules` Webtask](https://github.com/tehsis/webtaskio-canirequire/blob/gh-pages/tasks/list_modules.js) using the appropriate sandbox on your PSaaS Appliance instance.
+To see which modules are available for Webtasks running on PSaaS Appliance instances, execute the [`List Modules` Webtask](https://github.com/auth0-extensions/canirequire/blob/gh-pages/tasks/list_modules.js) on your PSaaS Appliance instance.
-First, copy locally the [`List Modules` Webtask](https://github.com/tehsis/webtaskio-canirequire/blob/gh-pages/tasks/list_modules.js), either by downloading the file or by copying this code:
+#### Set up the List Modules Webtask
+
+First, copy locally the [`List Modules` Webtask](https://github.com/auth0-extensions/canirequire/blob/gh-pages/tasks/list_modules.js), either by downloading the file from GitHub or by copying this code:
```js
'use npm';
@@ -88,13 +83,13 @@ module.exports = cb => {
};
```
-Afterwards, create a webtask profile using `wt-cli`, if you don't already have one.
+Next, create a Webtask profile using `wt-cli` (if you don't already have one):
```bash
wt init --container "YOUR_TENANT_NAME" --url "WEBTASK_URL" --token "eyJhbGci..." -p "a``YOUR_TENANT_NAME-default"
```
-Now you are ready to register your webtask, using the `wt create` command. This command receives as input a path or URL of the webtasks's code and provides as output the URL where the webtask is available.
+Finally, you are ready to register your Webtask using the `wt create` command. This command receives as input a path or URL of the ebtask's code and provides as output the URL where the Webtask is available.
If you saved the file under a `my-webtasks` directory as `list_modules.js` you would use the following:
@@ -102,8 +97,7 @@ If you saved the file under a `my-webtasks` directory as `list_modules.js` you w
wt create ./my-webtasks/list_modules.js
```
-You should get a message that the webtask was created, alongside with the URL to access it. The response is a JSON object.
-
+You should get a message that the Webtask was created, alongside with the URL to access it. The response is a JSON object.
```json
{
diff --git a/articles/application-auth/current/client-side-web.md b/articles/application-auth/current/client-side-web.md
index 94be5c6b0e..8d504faa5c 100644
--- a/articles/application-auth/current/client-side-web.md
+++ b/articles/application-auth/current/client-side-web.md
@@ -2,15 +2,25 @@
title: Authentication for Client-side Web Apps
description: Explains how to authenticate users in a Client-side Web application.
toc: true
+topics:
+ - spa
+ - authentication
+ - oauth2
+ - implicit
+contentType:
+ - concept
+ - how-to
+useCase:
+ - add-login
---
# Authentication for Client-side Web Apps
-The Auth0 OAuth 2.0 authentication endpoints support Client-side Web Applications. These applications are also referred to as JavaScript or Single Page Applications.
+You can use the Auth0 Authentication API to create client-side web applications that use [OpenID Connect](/protocols/oidc) and [OAuth 2.0](/protocols/oauth2) to authenticate users and get their authorization to access protected resources.
## Overview
-Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can redirect the user from your JavaScript application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to the Callback URL, returning an [ID Token](/tokens/id-token) and [Access Token](/tokens/access-token) in the hash fragment of the request.
+Auth0 exposes endpoints that you can use to authenticate users and get their authorization. You can redirect the user from your JavaScript application to these endpoints in the web browser. Auth0 will handle the authentication of the user, get their authorization for the resources your app wants to access, and then redirect the user back to a pre-configured callback URL, returning an [ID Token](/tokens/concepts/id-tokens) and [Access Token](/tokens/concepts/access-tokens) in the hash fragment of the request.
## The Authentication Flow
@@ -18,12 +28,12 @@ The OAuth 2.0 Authorization Framework allows for different kinds of authorizatio
The Implicit Grant flow is initiated by redirecting the user in the web browser to the Auth0 `/authorize` endpoint. Auth0 will then display the Auth0 Lock dialog, allowing the user to enter their credentials or alternatively sign in with any other configured [Identity Provider](/identityproviders).
-After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along the [ID Token](/tokens/id-token) as parameter in the [hash fragment](https://en.wikipedia.org/wiki/Fragment_identifier). The [ID Token](/tokens/id-token) is a [JSON Web Token (JWT)](/jwt) and contains various attributes (referred to as Claims) regarding the user, such as the user's name, email address, profile picture and so on.
+After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along the [ID Token](/tokens/concepts/id-tokens) as parameter in the [hash fragment](https://en.wikipedia.org/wiki/Fragment_identifier). The [ID Token](/tokens/concepts/id-tokens) is a [JSON Web Token (JWT)](/tokens/concepts/jwts) and contains various attributes (referred to as Claims) regarding the user, such as the user's name, email address, profile picture and so on.
-The [ID Token](/tokens/id-token) can be decoded to extract the claims and you are free to use these inside of your application, to display a user's name and profile image for example.
+The [ID Token](/tokens/concepts/id-tokens) can be decoded to extract the claims and you are free to use these inside of your application, to display a user's name and profile image for example.
::: note
-You can potentially also receive an `access_token` which can be used to call the [Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or your own APIs.
+You can potentially also receive an Access Token which can be used to call the [Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or your own APIs.
For more information on calling APIs from Client-side Web Apps, please see [Call APIs from Client-side Web Apps](/api-auth/grant/implicit)
:::
@@ -32,22 +42,22 @@ For more information on calling APIs from Client-side Web Apps, please see [Call
1. The Applications initiates the flow and redirects the user to the Authorization Server
2. The user authenticates
-3. The Authorization Server redirects the user to the `redirect_uri` with an `id_token` in the hash fragment
+3. The Authorization Server redirects the user to the `redirect_uri` with an ID Token in the hash fragment
4. The Applications can now extract the token from the hash fragment.
## Register your Applications
-The first thing you need to do is to create a new applications in Auth0. An Auth0 applications maps to your application and allows it to use Auth0 for authentication.
+The first thing you need to do is to create a new application in Auth0. An Auth0 application maps to your application and allows it to use Auth0 for authentication.
-Navigate to the [Auth0 Dashboard](${manage_url}) and click on the [Applicationss](${manage_url}/#/applicationss) menu option on the left. Create a new Application by clicking on the **Create Applications** button.
+Navigate to the [Auth0 Dashboard](${manage_url}) and click on the [Applications](${manage_url}/#/applications) menu option on the left. Create a new Application by clicking on the **Create Applications** button.
-The **Create Applications** window will open, allowing you to enter the name of your new application. Choose **Single Page Web Applications** as the **Applications Type** and click on the **Create** button to create the new applications.
+The **Create Applications** window will open, allowing you to enter the name of your new application. Choose **Single-Page Web Applications** as the **Applications Type** and click on the **Create** button to create the new applications.

-Once the applications has been created you can navigate to the **Settings** tab of the applications and in the **Allowed Callback URLs** field add a URL where Auth0 must redirect to after the user has authenticated, such as `https://YOUR_APP/callback`.
+Once the application has been created you can navigate to the **Settings** tab of the applications and in the **Allowed Callback URLs** field add a URL where Auth0 must redirect to after the user has authenticated, such as `https://YOUR_APP/callback`.
-This URL must be part of your application, as your application will need to extract the `id_token` from the hash fragment of this URL.
+This URL must be part of your application, as your application will need to extract the ID Token from the hash fragment of this URL.

@@ -59,17 +69,17 @@ Save the Settings.
## Call the Authorization URL
-The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any SSO session is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
+The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any Single Sign-on (SSO) session is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
This endpoint supports the following query string parameters:
| Parameter | Description |
|:------------------|:---------|
-| response_type | The response type specifies the Grant Type you want to use. For client-side web applications using the Implicit Grant Flow this should be `id_token`. (If you also want to receive an `access_token` it should be set to `token id_token`.) |
+| response_type | The response type specifies the Grant Type you want to use. For client-side web applications using the Implicit Grant Flow, this should be `id_token`. (If you also want to receive an Access Token it should be set to `token id_token`.) |
| client_id | The Client ID of the Applications you registered in Auth0. This can be found on the **Settings** tab of your Applications in the Auth0 Dashboard |
-| scope | Specifies the claims (or attributes) of the user you want the be returned in the [ID Token](/tokens/id-token). To obtain an [ID Token](/tokens/id-token) you need to specify at least a scope of `openid`. If you want to return the user's full profile information, you can request `openid profile`.
You can read up more about [scopes](/scopes). |
+| scope | Specifies the claims (or attributes) of the user you want the be returned in the [ID Token](/tokens/concepts/id-tokens). To obtain an [ID Token](/tokens/concepts/id-tokens) you need to specify at least a scope of `openid`. If you want to return the user's full profile information, you can request `openid profile`.
You can read up more about [scopes](/scopes). |
| redirect_uri | The URL in your application where the user will be redirected to after they have authenticated, such as `https://YOUR_APP/callback`|
-| connection | This is an optional parameter which allows you to force the user to sign in with a specific connection. You can for example pass a value of `github` to send the user directly to GitHub to log in with their GitHub account.
If this parameter is not specified the user will be presented with the normal Auth0 Lock screen from where they can sign in with any of the available connections. You can see the list of configured connections on the **Connections** tab of your applications. |
+| connection | This is an optional parameter which allows you to force the user to sign in with a specific connection. You can for example pass a value of `github` to send the user directly to GitHub to log in with their GitHub account.
If this parameter is not specified, the user will be presented with the normal Auth0 Lock screen from where they can sign in with any of the available connections. You can see the list of configured connections on the **Connections** tab of your applications. |
| state | The state parameter will be sent back should be used for CSRF and contextual information (like a return url) |
| nonce | A string value which will be included in the response from Auth0, [used to prevent token replay attacks](/api-auth/tutorials/nonce). **This is required.** |
@@ -79,19 +89,19 @@ This endpoint supports the following query string parameters:
## Handle the callback
-After the user has authenticated, Auth0 will call back to the URL specified in the `redirect_uri` query string parameter which was passed to the `/authorize` endpoint. When calling back to this URL, Auth0 will pass along the [ID Token](/tokens/id-token) in the hash fragment of the URL, such as
+After the user has authenticated, Auth0 will call back to the URL specified in the `redirect_uri` query string parameter which was passed to the `/authorize` endpoint. When calling back to this URL, Auth0 will pass along the [ID Token](/tokens/concepts/id-tokens) in the hash fragment of the URL, such as
```text
https://YOUR_APP/callback#id_token=eyJ0...
```
-The [ID Token](/tokens/id-token) will be a [JSON Web Token (JWT)](/jwt) containing information about the user. You can access the hash fragment using the `window.location.hash` property and then use basic JavaScript string manipulation to access the `id_token`.
+The [ID Token](/tokens/concepts/id-tokens) will be a [JSON Web Token (JWT)](/tokens/concepts/jwts) containing information about the user. You can access the hash fragment using the `window.location.hash` property and then use basic JavaScript string manipulation to access the ID Token.
-You will need to decode the [ID Token](/tokens/id-token) in order to read the claims (or attributes) of the user. The [JWT section of our website](/jwt) contains more information about the structure of a JWT.
+You will need to decode the [ID Token](/tokens/concepts/id-tokens) in order to read the claims (or attributes) of the user.
-Once the JWT is decoded, you can extract the information about the user from the payload of the [ID Token](/tokens/id-token). This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
+Once the JWT is decoded, you can extract the information about the user from the payload of the [ID Token](/tokens/concepts/id-tokens). This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
-The [Auth0.js library](https://auth0.com/docs/libraries/auth0js) can assist you in decoding the JWT by calling the `parseHash` function, and then access the `id_token` values from the `idTokenPayload` property:
+The [Auth0.js library](https://auth0.com/docs/libraries/auth0js) can assist you in decoding the JWT by calling the `parseHash` function, and then access the ID Token values from the `idTokenPayload` property:
```html
@@ -128,7 +138,7 @@ The [Auth0.js library](https://auth0.com/docs/libraries/auth0js) can assist you
if (authResult && authResult.idTokenPayload) {
window.location.hash = '';
alert('your user_id is: ' + authResult.idTokenPayload.sub);
- }
+ }
});
}
@@ -141,7 +151,7 @@ The [Auth0.js library](https://auth0.com/docs/libraries/auth0js) can assist you
### The ID Token payload
-An example payload for an [ID Token](/tokens/id-token) may look something like this:
+An example payload for an [ID Token](/tokens/concepts/id-tokens) may look something like this:
```json
{
@@ -165,13 +175,13 @@ The payload above contains the following claims:
| email | The email address of the user which is returned from the Identity Provider. |
| picture | The profile picture of the user which is returned from the Identity Provider. |
| sub | The unique identifier of the user. This is guaranteed to be unique per user and will be in the format (identity provider)|(unique id in the provider), such as github|1234567890. |
-| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued [ID Token](/tokens/id-token), this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
-| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued [ID Token](/tokens/id-token), this will be the **Client ID of your Auth0 Applications**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued [ID Token](/tokens/concepts/id-tokens), this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued [ID Token](/tokens/concepts/id-tokens), this will be the **Client ID of your Auth0 Applications**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| exp | The _expiration time_. A number representing a specific date and time in the format “seconds since epoch” as [defined by POSIX6](https://en.wikipedia.org/wiki/Unix_time). This claim sets the exact moment from which this **JWT is considered invalid**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| iat | The _issued at time_. A number representing a specific date and time (in the same format as `exp`) at which this **JWT was issued**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| nonce | A string value which was sent with the request to the `/authorize` endpoint. This is used to [prevent token replay attacks](/api-auth/tutorials/nonce). |
-The exact claims contained in the [ID Token](/tokens/id-token) will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an [ID Token](/tokens/id-token) issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
+The exact claims contained in the [ID Token](/tokens/concepts/id-tokens) will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an [ID Token](/tokens/concepts/id-tokens) issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
::: note
The [JWT.io website](https://jwt.io) has a handy debugger which will allow you to debug any JSON Web Token. This is useful is you quickly want to decode a JWT to see the information contained in the token.
@@ -179,7 +189,7 @@ The [JWT.io website](https://jwt.io) has a handy debugger which will allow you t
### Keep the user logged in
-Auth0 will assist you in authenticating a user, but it is up to you to keep track in your application of whether or not a user is logged in. You can use `localStorage` to keep track of whether a user is logged in or not, and also to store the claims of the user which was extracted from the [ID Token](/tokens/id-token).
+Auth0 will assist you in authenticating a user, but it is up to you to keep track in your application of whether or not a user is logged in. You can use `localStorage` to keep track of whether a user is logged in or not, and also to store the claims of the user which was extracted from the [ID Token](/tokens/concepts/id-tokens).
You can then use those claims inside of your application to display the user's information or otherwise personalize the user's experience.
@@ -204,7 +214,7 @@ ${account.callback}
#id_token=eyJ0...
```
-And this is an example of the decoded payload of the [ID Token](/tokens/id-token) which will be returned:
+And this is an example of the decoded payload of the [ID Token](/tokens/concepts/id-tokens) which will be returned:
```json
{
@@ -237,7 +247,7 @@ ${account.callback}
#id_token=eyJ0...
```
-The name and profile picture will be available in the `name` and `picture` claims of the returned [ID Token](/tokens/id-token):
+The name and profile picture will be available in the `name` and `picture` claims of the returned [ID Token](/tokens/concepts/id-tokens):
```json
{
@@ -279,7 +289,7 @@ ${account.callback}
#id_token=eyJ0...
```
-The user's name and profile attributes, such as the name, nickname and picture will be available in the `name`, `nickname` and `picture` claims of the returned [ID Token](/tokens/id-token). You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
+The user's name and profile attributes, such as the name, nickname and picture will be available in the `name`, `nickname` and `picture` claims of the returned [ID Token](/tokens/concepts/id-tokens). You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
```json
{
diff --git a/articles/application-auth/current/index.md b/articles/application-auth/current/index.md
index b332be79b6..685c9b3586 100644
--- a/articles/application-auth/current/index.md
+++ b/articles/application-auth/current/index.md
@@ -1,17 +1,35 @@
---
classes: topic-page
title: Application Authentication
-description: Introduction to the various application authentication flows.
+description: Introduction to authentication and the various application authentication flows.
+topics:
+ - authentication
+ - oauth2
+contentType: index
+useCase:
+ - add-login
---
-# Application Authentication
+# Authentication
-Auth0 uses the OAuth 2.0 protocol for authentication and authorization. We support common OAuth 2.0 scenarios for Mobile Applications, Desktop Applications, Server-side web applications or Client-side Web Applications.
+Authentication refers to the process of confirming identity. While often used interchangeably with [authorization](/authorization), authentication represents a fundamentally different function.
-You can get more details on implementing these flows by following one of the following links:
+In authentication, a user or application proves they are who they say they are by providing valid credentials for verification. Authentication is often proved through a username and password, sometimes combined with other elements called _factors_, which fall into three categories: what you know, what you have, or what you are.
+
+* **Single-Factor Authentication** relies on a password. Example: a school website that only requires validating a password against a username.
+* **Two-Factor Authentication** relies on a piece of confidential information in addition to a username and password. Example: a banking website that validates a password against a username and then requires the user to enter a PIN known to only the user.
+* **Multi-Factor Authentication (MFA)** uses two or more security factors from independent categories. Example: a hospital system that requires a username and password, a security code received on the user's smartphone, and fingerprint.
+
+For a comparison of authentication and authorization, see [Authentication vs. Authorization](/authorization/concepts/authz-and-authn).
+
+# Application Authentication Flows
+
+Auth0 uses [OpenID Connect](/protocols/oidc) and [OAuth 2.0](/protocols/oauth2) to authenticate users and verify their identity.
+
+We support scenarios for mobile, desktop, server-side, or client-side applications. You can get more details on implementing these flows by exploring:
<%= include('../../_includes/_topic-links', { links: [
- 'application-auth/current/mobile-desktop',
- 'application-auth/current/server-side-web',
- 'application-auth/current/client-side-web'
+ 'flows/guides/auth-code-pkce/add-login-auth-code-pkce',
+ 'flows/guides/implicit/add-login-implicit',
+ 'flows/guides/auth-code/add-login-auth-code'
] }) %>
diff --git a/articles/application-auth/current/mobile-desktop.md b/articles/application-auth/current/mobile-desktop.md
index 57847be51b..183b936bb5 100644
--- a/articles/application-auth/current/mobile-desktop.md
+++ b/articles/application-auth/current/mobile-desktop.md
@@ -2,6 +2,16 @@
title: Authentication for Mobile & Desktop Apps
description: Explains how to authenticate users in a mobile or desktop application.
toc: true
+topics:
+ - authentication
+ - oauth2
+ - mobile-apps
+ - desktop-apps
+contentType:
+ - concept
+ - how-to
+useCase:
+ - add-login
---
# Authentication for Mobile & Desktop Apps
@@ -11,7 +21,7 @@ You can authenticate users of your mobile/desktop applications by:
* Using one of the [Auth0 SDKs](/libraries), which are client-side libraries that **do not** include a user interface but allow for expanded customization of the authentication behavior and appearance of the login screen;
* Calling the Auth0 [Authentication API](/api/authentication) endpoints, which allows you to integrate with Auth0 without requiring the user of Auth0's libraries.
-This article will cover how to call the Auth0 [Authentication API](/api/authentication) endpoints using [Proof Key for Code Exchange (PKCE)](/api-auth/grant/authorization-code-pkce) during the authentication process.
+This article will cover how to call the Auth0 [Authentication API](/api/authentication) endpoints using [Proof Key for Code Exchange (PKCE)](/api-auth/grant/authorization-code-pkce) during the authentication and authorization process.
If you would like to implement this functionality using either Lock or one of the Auth0 SDKs, please refer to the following resources:
@@ -26,15 +36,17 @@ If you would like to implement this functionality using either Lock or one of th
## Overview
-Auth0 exposes OAuth 2.0 endpoints that you can use to authenticate users. You can call these endpoints through an embedded browser in your **native** application. After authentication completes, you can return an [ID Token](/tokens/id-token) that contains the user's profile information.
+Auth0 exposes endpoints that you can use to authenticate users and get their authorization.
+
+You can call these endpoints through an embedded browser in your **native** application. After authentication completes, you can return an [ID Token](/tokens/concepts/id-tokens) (which contains information about the identity of the user) and an [Access Token](/tokens/concepts/access-tokens).
::: note
-Instead of following this tutorial, you can use any of Auth0's client libraries. These encapsulate all the logic required and make it easier for your to implement authentication. Please refer to our [Native Quickstarts](/quickstart/native) to get started.
+Instead of following this tutorial, you can use any of Auth0's client libraries. They encapsulate all the logic required and make it easier for your to implement authentication. Please refer to our [Native Quickstarts](/quickstart/native) to get started.
:::
-## Register Your Application
+## Register your application
-If you haven't already created a new [Application](/applications) in Auth0, you'll need to do so before implementing your authentication flow. The Auth0 Application maps to your application and allows your application to use Auth0 for authentication purposes.
+If you haven't already created a new [application](/applications) in Auth0, you'll need to do so before implementing your authentication flow. The Auth0 Application maps to your application and allows your application to use Auth0 for authentication purposes.
Go to the [Auth0 Dashboard](${manage_url}) and click on [Applications](${manage_url}/#/applications) in the left-hand navigation bar. Click **Create Application**.
@@ -71,7 +83,7 @@ Once you've created the `code_verifier` and the `code_challenge`, you'll need to
* Authenticating the user;
* Redirecting the user to an Identity Provider to handle authentication;
-* Checking for active SSO sessions.
+* Checking for active Single Sign-on (SSO) [sessions](/sessions).
To authorize the user, your application must send the user to the [authorization URL](/api/authentication#authorization-code-grant-pkce-) (which includes the `code_challenge` you generated in the previous step, as well as the method you used to generate the `code_challenge`). Your URL should follow this format:
@@ -121,11 +133,32 @@ Using the authorization code obtained in step 2, you can obtain the ID Token by
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://${account.namespace}/mobile\" }"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "code_verifier",
+ "value": "YOUR_GENERATED_CODE_VERIFIER"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "https://${account.namespace}/mobile"
+ }
+ ]
}
}
```
@@ -145,7 +178,7 @@ If all goes well, you'll receive an HTTP 200 response with the following payload
```
::: note
-You can use the `access_token` to call the [Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info).
+You can use the Access Token to call the [Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info).
:::
## The ID Token
@@ -165,7 +198,7 @@ Once you've decoded the ID Token, you can extract user information from it. The
}
```
-For additional details, please see our docs [on the ID Token and its claims](/tokens/id-token#id-token-payload).
+For additional details, please see our docs [on the ID Token and its claims](/tokens/id-tokens#id-token-payload).
::: note
For a list of libraries you can use to verify and decode tokens refer to [JWT.io](https://jwt.io/#libraries-io).
@@ -202,11 +235,32 @@ Using the authorization code, you can obtain the ID Token by making a `POST` cal
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"${account.namespace}/mobile\" }"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "code_verifier",
+ "value": "YOUR_GENERATED_CODE_VERIFIER"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "https://${account.namespace}/mobile"
+ }
+ ]
}
}
```
@@ -223,7 +277,7 @@ If all goes well, you'll receive an HTTP 200 response with the following payload
}
```
-By extracting the `id_token`, which now contains the additional `name` and `picture` claims you requested, you'll see something similar to the following once you've decoded the payload:
+By extracting the ID Token, which now contains the additional `name` and `picture` claims you requested, you'll see something similar to the following once you've decoded the payload:
```json
{
@@ -272,11 +326,32 @@ Using the authorization code, you can obtain the ID Token by making a `POST` cal
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"${account.namespace}/mobile\" }"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "code_verifier",
+ "value": "YOUR_GENERATED_CODE_VERIFIER"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "https://${account.namespace}/mobile"
+ }
+ ]
}
}
```
@@ -293,7 +368,7 @@ If all goes well, you'll receive an `HTTP 200` response with the following paylo
}
```
-You can pull the user's name, profile picture, and email address from the `name`, `picture`, and `email` claims of the returned `id_token`. Note that the `sub` claim contains the user's unique ID as returned from GitHub:
+You can pull the user's name, profile picture, and email address from the `name`, `picture`, and `email` claims of the returned ID Token. Note that the `sub` claim contains the user's unique ID as returned from GitHub:
```json
{
diff --git a/articles/application-auth/current/server-side-web.md b/articles/application-auth/current/server-side-web.md
index ca2980a9a2..026aa3dab9 100644
--- a/articles/application-auth/current/server-side-web.md
+++ b/articles/application-auth/current/server-side-web.md
@@ -2,15 +2,26 @@
title: Authentication for Server-side Web Apps
description: Explains how to authenticate users in a Server-side Web application.
toc: true
+topics:
+ - oauth2
+ - authentication
+ - server-side-apps
+contentType:
+ - concept
+ - how-to
+useCase:
+ - add-login
---
# Authentication for Server-side Web Apps
-You can use the Auth0 Authentication API to create server-side web applications that uses OAuth 2.0 authorization to authenticate users.
+You can use the Auth0 Authentication API to create server-side web applications that uses OAuth 2.0 and OpenID Connect (OIDC) to authenticate users and get their authorization to access protected resources.
## Overview
-Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can redirect the user from your web application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to the `redirect_uri` (also referred to as the Callback URL), returning an authorization `code` in the query string parameters of the Callback URL. This `code` can then be exchanged for an [ID Token](/tokens/id-token) which contains the identity of the user.
+Auth0 exposes endpoints that you can use to authenticate users and get their authorization.
+
+You can redirect the user from your web application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to a pre-configured callback URL, returning an authorization code in the query string parameters of the callback URL. This code can then be exchanged for an [ID Token](/tokens/concepts/id-tokens) (which contains information about the identity of the user) and an [Access Token](/tokens/concepts/access-tokens).
## The Authentication Flow
@@ -18,12 +29,12 @@ The OAuth 2.0 Authorization Framework allows for different kinds of authorizatio
The Authorization Code flow is initiated by redirecting the user in the web browser to the Auth0 `/authorize` endpoint. Auth0 will then display the Auth0 Lock dialog, allowing the user to enter their credentials or alternatively sign in with any other configured [Identity Provider](/identityproviders).
-After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along a `code` parameter in the query string of the Callback URL. This `code` can then be exchanged for an [ID Token](/tokens/id-token) by making a request to the `/oauth/token` endpoint.
+After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along a `code` parameter in the query string of the Callback URL. This `code` can then be exchanged for an [ID Token](/tokens/concepts/id-tokens) by making a request to the `/oauth/token` endpoint.
-The ID Token is a [JSON Web Token (JWT)](/jwt) and contains various attributes regarding the user, such as the user's name, email address, profile picture and so on. These attributes are referred to as **Claims** and they can be extracted from the ID Token and used in your application (for example, to display a user's name and profile image).
+The ID Token is a [JSON Web Token (JWT)](/tokens/concepts/jwts) and contains various attributes regarding the user, such as the user's name, email address, profile picture and so on. These attributes are referred to as **Claims** and they can be extracted from the ID Token and used in your application (for example, to display a user's name and profile image).
::: note
-You will also receive an [Access Token](/tokens/access-token) which you can use to call the [Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or your own APIs. For more information on calling APIs web apps running on the server, see [Calling APIs from Server-side Web Apps](/api-auth/grant/authorization-code)
+You will also receive an [Access Token](/tokens/concepts/access-tokens) which you can use to call the [Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or your own APIs. For more information on calling APIs web apps running on the server, see [Calling APIs from Server-side Web Apps](/api-auth/grant/authorization-code)
:::

@@ -58,7 +69,7 @@ Save the Settings.
## Call the Authorization URL
-The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any SSO session is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
+The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any Single Sign-on (SSO) [session](/sessions) is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
This endpoint supports the following query string parameters:
@@ -89,11 +100,32 @@ You application will need to handle the request to this callback URL, extract th
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"${account.callback}\"}"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "https://${account.callback}"
+ }
+ ]
}
}
```
@@ -109,7 +141,7 @@ The response from `/oauth/token` contains `access_token`, `expires_in`, `id_toke
}
```
-The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/jwt) containing information about the user. You will need to decode the `id_token` in order to read the claims (or attributes) of the user. The [JWT section of our website](/jwt) contains more information about the structure of a JWT.
+The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/tokens/concepts/jwts) containing information about the user. You will need to decode the ID Token in order to read the claims (or attributes) of the user. The [JWT section of our website](/tokens/concepts/jwts) contains more information about the structure of a JWT.
You can refer to the [libraries section on the JWT.io website](https://jwt.io/#libraries-io) in order to obtain a library for your programming language of choice which will assist you in decoding the ID Token.
@@ -178,7 +210,7 @@ After the user has authenticated, they will be redirected back to the `redirect_
${account.callback}?code=2OKj...
```
-You can then exchange the `code` for an ID Token. This is an example of the decoded payload of the `id_token` which will be returned:
+You can then exchange the `code` for an ID Token. This is an example of the decoded payload of the ID Token which will be returned:
```json
{
@@ -208,7 +240,7 @@ After the user has authenticated, they will be redirected back to the `redirect_
${account.callback}?code=2OKj...
```
-You can then exchange the `code` for an ID Token. The profile attributes of the user, such as the name and profile picture will be available in the `name` and `picture` claims of the returned `id_token`:
+You can then exchange the `code` for an ID Token. The profile attributes of the user, such as the name and profile picture will be available in the `name` and `picture` claims of the returned ID Token:
```json
{
diff --git a/articles/application-auth/legacy/client-side-web.md b/articles/application-auth/legacy/client-side-web.md
index 31611ec17b..da677b5d3a 100644
--- a/articles/application-auth/legacy/client-side-web.md
+++ b/articles/application-auth/legacy/client-side-web.md
@@ -1,6 +1,16 @@
---
description: Explains how to authenticate users in a Client-side Web application.
toc: true
+topics:
+ - spa
+ - authentication
+ - oauth2
+ - implicit
+contentType:
+ - concept
+ - how-to
+useCase:
+ - add-login
---
# Authentication for Client-side Web Apps
@@ -8,11 +18,11 @@ toc: true
This document covers an outdated version of the Auth0 authentication pipeline. We recommend you use the current version, using the dropdown. For more on the latest authentication pipeline refer to [Introducing OIDC Conformant Authentication](/api-auth/intro).
:::
-The Auth0 OAuth 2.0 authentication endpoints support Client-side Web Applications. These applications are also referred to as JavaScript or Single Page Applications.
+The Auth0 OAuth 2.0 authentication endpoints support Client-side Web Applications. These applications are also referred to as JavaScript or Single-Page Applications.
## Overview
-Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can redirect the user from your JavaScript application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to the Callback URL, returning the `id_token` in the hash fragment of the request.
+Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can redirect the user from your JavaScript application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to the Callback URL, returning the ID Token in the hash fragment of the request.
## The Authentication Flow
@@ -20,15 +30,15 @@ The OAuth 2.0 Authorization Framework allows for different kinds of authorizatio
The Implicit Grant flow is initiated by redirecting the user in the web browser to the Auth0 `/authorize` endpoint. Auth0 will then display the Auth0 Lock dialog, allowing the user to enter their credentials or alternatively sign in with any other configured [Identity Provider](/identityproviders).
-After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along an `id_token` parameter in the [hash fragment](https://en.wikipedia.org/wiki/Fragment_identifier). The `id_token` is a [JSON Web Token (JWT)](/jwt) and contains various attributes - referred to as _Claims_ - regarding the user, such as the user's name, email address, profile picture and so on.
+After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along an `id_token` parameter in the [hash fragment](https://en.wikipedia.org/wiki/Fragment_identifier). The ID Token is a [JSON Web Token (JWT)](/tokens/concepts/jwts) and contains various attributes - referred to as _Claims_ - regarding the user, such as the user's name, email address, profile picture and so on.
-The `id_token` can be decoded to extract the claims and you are free to use these inside of your application, to display a user's name and profile image for example.
+The ID Token can be decoded to extract the claims and you are free to use these inside of your application, to display a user's name and profile image for example.

1. The Application initiates the flow and redirects the user to the Authorization Server
2. The user authenticates
-3. The Authorization Server redirects the user to the `redirect_uri` with an `id_token` in the hash fragment
+3. The Authorization Server redirects the user to the `redirect_uri` with an ID Token in the hash fragment
4. The Application can now extract the token from the hash fragment.
## Register your Application
@@ -37,19 +47,19 @@ The first thing you need to do is to create a new application in Auth0. An Auth0
Navigate to the [Auth0 Dashboard](${manage_url}) and click on the [Applications](${manage_url}/#/applications) menu option on the left. Create a new Application by clicking on the **Create Application** button.
-The **Create Application** window will open, allowing you to enter the name of your new application. Choose **Single Page Web Applications** as the **Application Type** and click on the **Create** button to create the new application.
+The **Create Application** window will open, allowing you to enter the name of your new application. Choose **Single-Page Web Applications** as the **Application Type** and click on the **Create** button to create the new application.

Once the application has been created you can navigate to the **Settings** tab of the application and in the **Allowed Callback URLs** field add a URL where Auth0 must redirect to after the user has authenticated, such as `https://YOUR_APP/callback`.
-This URL must be part of your application, as your application will need to extract the `id_token` from the hash fragment of this URL. Save the Settings.
+This URL must be part of your application, as your application will need to extract the ID Token from the hash fragment of this URL. Save the Settings.

## Call the Authorization URL
-The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any SSO session is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
+The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any Single Sign-on (SSO) [session](/sessions) is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
This endpoint supports the following query string parameters:
@@ -57,7 +67,7 @@ This endpoint supports the following query string parameters:
|:------------------|:---------|
| response_type | The response type specifies the Grant Type you want to use. This can be either `code` or `token`. For client-side web applications using the Implicit Grant Flow this **must be set** to `token` |
| client_id | The Client ID of the Application you registered in Auth0. This can be found on the **Settings** tab of your Application in the Auth0 Dashboard |
-| scope | Specifies the claims (or attributes) of the user you want the be returned in the `id_token`. To obtain an `id_token` you need to specify at least a scope of `openid` (if no scope is specified then `openid` is implied). You can also request other scopes, so for example to return the user's name and profile picture you can request a scope of `openid name picture`.
You can read up more about [scopes](/scopes). |
+| scope | Specifies the claims (or attributes) of the user you want the be returned in the ID Token. To obtain an ID Token you need to specify at least a scope of `openid` (if no scope is specified then `openid` is implied). You can also request other scopes, so for example to return the user's name and profile picture you can request a scope of `openid name picture`.
You can read up more about [scopes](/scopes). |
| redirect_uri | The URL in your application where the user will be redirected to after they have authenticated, such as `${account.callback}`.|
| connection | This is an optional parameter which allows you to force the user to sign in with a specific connection. You can for example pass a value of `github` to send the user directly to GitHub to log in with their GitHub account.
If this parameter is not specified the user will be presented with the normal Auth0 Lock screen from where they can sign in with any of the available connections. You can see the list of configured connections on the **Connections** tab of your application. |
| state | The state parameter will be sent back should be used for CSRF and contextual information (like a return url) |
@@ -69,19 +79,19 @@ This endpoint supports the following query string parameters:
## Handle the callback
-After the user has authenticated, Auth0 will call back to the URL specified in the `redirect_uri` query string parameter which was passed to the `/authorize` endpoint. When calling back to this URL, Auth0 will pass along the `id_token` and the `token_type` in the hash fragment of the URL, such as
+After the user has authenticated, Auth0 will call back to the URL specified in the `redirect_uri` query string parameter which was passed to the `/authorize` endpoint. When calling back to this URL, Auth0 will pass along the ID Token and the `token_type` in the hash fragment of the URL, such as
```text
https://YOUR_APP/callback#id_token=eyJ0...&token_type=Bearer
```
-The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/jwt) containing information about the user. You can access the hash fragment using the `window.location.hash` property and then use basic JavaScript string manipulation to access the `id_token`.
+The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/tokens/concepts/jwts) containing information about the user. You can access the hash fragment using the `window.location.hash` property and then use basic JavaScript string manipulation to access the ID Token.
-As mentioned, the `id_token` is a JWT and you will need to decode this token in order to read the claims (or attributes) of the user. The [JWT section of our website](/jwt) contains more information about the structure of a JWT.
+As mentioned, the ID Token is a JWT and you will need to decode this token in order to read the claims (or attributes) of the user. The [JWT section of our website](/tokens/concepts/jwts) contains more information about the structure of a JWT.
-Once the JWT is decoded, you can extract the information about the user from the Payload of the `id_token`. This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
+Once the JWT is decoded, you can extract the information about the user from the Payload of the ID Token. This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
-The [Auth0.js library](https://auth0.com/docs/libraries/auth0js) can assist you in decoding the JWT by calling the `parseHash` function, and then access the `id_token` values from the `idTokenPayload` property:
+The [Auth0.js library](https://auth0.com/docs/libraries/auth0js) can assist you in decoding the JWT by calling the `parseHash` function, and then access the ID Token values from the `idTokenPayload` property:
```
@@ -108,9 +118,9 @@ The [Auth0.js library](https://auth0.com/docs/libraries/auth0js) can assist you
```
-### The `id_token` Payload
+### The ID Token Payload
-An example payload for an `id_token` may look something like this:
+An example payload for an ID Token may look something like this:
```json
{
@@ -133,12 +143,12 @@ The payload above contains the following claims:
| email | The email address of the user which is returned from the Identity Provider. |
| picture | The profile picture of the user which is returned from the Identity Provider. |
| sub | The unique identifier of the user. This is guaranteed to be unique per user and will be in the format (identity provider)|(unique id in the provider), such as github|1234567890. |
-| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued `id_token`, this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
-| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued `id_token`, this will be the **Client ID of your Auth0 Application**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued ID Token, this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued ID Token, this will be the **Client ID of your Auth0 Application**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| exp | The _expiration time_. A number representing a specific date and time in the format “seconds since epoch” as [defined by POSIX6](https://en.wikipedia.org/wiki/Unix_time). This claim sets the exact moment from which this **JWT is considered invalid**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| iat | The _issued at time_. A number representing a specific date and time (in the same format as `exp`) at which this **JWT was issued**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
-The exact claims contained in the `id_token` will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an `id_token` issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
+The exact claims contained in the ID Token will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an ID Token issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
::: note
The [JWT.io website](https://jwt.io) has a handy debugger which will allow you to debug any JSON Web Token. This is useful is you quickly want to decode a JWT to see the information contained in the token.
@@ -146,7 +156,7 @@ The [JWT.io website](https://jwt.io) has a handy debugger which will allow you t
### Keep the user logged in
-Auth0 will assist you in authenticating a user, but it is up to you to keep track in your application of whether or not a user is logged in. You can use `localStorage` to keep track of whether a user is logged in or not, and also to store the claims of the user which was extracted from the `id_token`.
+Auth0 will assist you in authenticating a user, but it is up to you to keep track in your application of whether or not a user is logged in. You can use `localStorage` to keep track of whether a user is logged in or not, and also to store the claims of the user which was extracted from the ID Token.
You can then use those claims inside of your application to display the user's information or otherwise personalize the user's experience.
@@ -163,7 +173,7 @@ https://${account.namespace}/authorize
&redirect_uri=${account.callback}
```
-After the user has authenticated, they will be redirected back to the `redirect_uri` with the `id_token` and `token_type` passed as parameters in the hash fragment:
+After the user has authenticated, they will be redirected back to the `redirect_uri` with the ID Token and `token_type` passed as parameters in the hash fragment:
```text
${account.callback}
@@ -171,7 +181,7 @@ ${account.callback}
&token_type=Bearer
```
-And this is an example of the decoded payload of the `id_token` which will be returned:
+And this is an example of the decoded payload of the ID Token which will be returned:
```json
{
@@ -195,7 +205,7 @@ https://${account.namespace}/authorize
&scope=openid%20name%20picture
```
-After the user has authenticated, they will be redirected back to the `redirect_uri` with the `id_token` and `token_type` passed as parameters in the hash fragment:
+After the user has authenticated, they will be redirected back to the `redirect_uri` with the ID Token and `token_type` passed as parameters in the hash fragment:
```text
${account.callback}
@@ -203,7 +213,7 @@ ${account.callback}
&token_type=Bearer
```
-The name and profile picture will be available in the `name` and `picture` claims of the returned `id_token`:
+The name and profile picture will be available in the `name` and `picture` claims of the returned ID Token:
```json
{
@@ -236,7 +246,7 @@ You can just as easily request a user log in with other social providers, like G
- [Social Login using the Authentication API](/api/authentication#social)
:::
-After the user has authenticated, they will be redirected back to the `redirect_uri` with the `id_token` and `token_type` passed as parameters in the hash fragment:
+After the user has authenticated, they will be redirected back to the `redirect_uri` with the ID Token and `token_type` passed as parameters in the hash fragment:
```text
${account.callback}
@@ -244,7 +254,7 @@ ${account.callback}
&token_type=Bearer
```
-The user's name and profile picture and email address will be available in the `name`, `picture` and `email` claims of the returned `id_token`. You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
+The user's name and profile picture and email address will be available in the `name`, `picture` and `email` claims of the returned ID Token. You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
```json
{
diff --git a/articles/application-auth/legacy/index.md b/articles/application-auth/legacy/index.md
index b36f669b6d..56a74c0a5b 100644
--- a/articles/application-auth/legacy/index.md
+++ b/articles/application-auth/legacy/index.md
@@ -2,6 +2,12 @@
classes: topic-page
title: Application Authentication
description: Introduction to the various application authentication flows.
+topics:
+ - authentication
+ - oauth2
+contentType: index
+useCase:
+ - add-login
---
# Application Authentication
diff --git a/articles/application-auth/legacy/mobile-desktop.md b/articles/application-auth/legacy/mobile-desktop.md
index bb9bb772bb..04b9497aee 100644
--- a/articles/application-auth/legacy/mobile-desktop.md
+++ b/articles/application-auth/legacy/mobile-desktop.md
@@ -1,6 +1,16 @@
---
-description: Explains how to authenticate users in a mobile or desktop application.
+description: Explains how to authenticate users in a mobile or desktop application.
toc: true
+topics:
+ - authentication
+ - oauth2
+ - mobile-apps
+ - desktop-apps
+contentType:
+ - concept
+ - how-to
+useCase:
+ - add-login
---
# Authentication for Mobile & Desktop Apps
@@ -8,11 +18,11 @@ toc: true
This document covers an outdated version of the Auth0 authentication pipeline. We recommend you use the current version, using the dropdown. For more on the latest authentication pipeline refer to [Introducing OIDC Conformant Authentication](/api-auth/intro).
:::
-You can easily authenticate users in your mobile and desktop applications by using either the Lock application libraries, or by calling the Auth0 OAuth 2.0 endpoints yourself.
+You can easily authenticate users in your mobile and desktop applications by using either the Lock application libraries, or by calling the Auth0 OAuth 2.0 endpoints yourself.
## Overview
-Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can call these endpoints through an embedded browser in your application, and then intercept the request to the callback URL to extract the `id_token` which contains the user's profile information.
+Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can call these endpoints through an embedded browser in your application, and then intercept the request to the callback URL to extract the ID Token which contains the user's profile information.
We also make a set of application libraries available which encapsulates all the logic for you and makes it much easier to implement authentication in all the popular mobile and desktop platforms. Please refer to our [Native Quickstarts](/quickstart/native) to get started with any of these.
@@ -22,15 +32,15 @@ The OAuth 2.0 Authorization Framework allows for different kinds of authorizatio
The Implicit Grant flow is initiated by redirecting the user in an embedded web browser inside of your application to the Auth0 `/authorize` endpoint. Auth0 will then display the Auth0 Lock dialog, allowing the user to enter their credentials or alternatively sign in with any other configured [Identity Provider](/identityproviders).
-After the user has authenticated, Auth0 will redirect the browser back to the `redirect_uri` (also known as the **Callback URL**), passing along an `id_token` parameter in the [hash fragment](https://en.wikipedia.org/wiki/Fragment_identifier) or the URL. The `id_token` is a [JSON Web Token (JWT)](/jwt) and contains various attributes - referred to as _Claims_ - regarding the user, such as the user's name, email address, profile picture and so on.
+After the user has authenticated, Auth0 will redirect the browser back to the `redirect_uri` (also known as the **Callback URL**), passing along an `id_token` parameter in the [hash fragment](https://en.wikipedia.org/wiki/Fragment_identifier) or the URL. The ID Token is a [JSON Web Token (JWT)](/tokens/concepts/jwts) and contains various attributes - referred to as _Claims_ - regarding the user, such as the user's name, email address, profile picture and so on.
-The `id_token` can be decoded to extract the claims and you can use these inside of your application, to display a user's name and profile image for example.
+The ID Token can be decoded to extract the claims and you can use these inside of your application, to display a user's name and profile image for example.

1. The Application initiates the flow and redirects the user to the Authorization Server
2. The user authenticates
-3. The Authorization Server redirects the user to the `redirect_uri` with an `id_token` in the hash fragment
+3. The Authorization Server redirects the user to the `redirect_uri` with an ID Token in the hash fragment
4. The Application can now extract the token from the hash fragment.
## Register your Application
@@ -41,7 +51,7 @@ Navigate to the [Auth0 Dashboard](${manage_url}) and click on the [Applications]
The **Create Application** window will open, allowing you to enter the name of your new application. Choose **Native** as the **Application Type** and click on the **Create** button to create the new application.
-
+
Once the application has been created you can navigate to the **Settings** tab of the application and in the **Allowed Callback URLs** field add the URL `https://${account.namespace}/mobile`. Save the Settings.
@@ -49,7 +59,7 @@ Once the application has been created you can navigate to the **Settings** tab o
## Call the Authorization URL
-The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any SSO session is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
+The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any Single Sign-on (SSO) [session](/sessions) is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
This endpoint supports the following query string parameters:
@@ -57,7 +67,7 @@ This endpoint supports the following query string parameters:
|:------------------|:---------|
| response_type | The response type specifies the Grant Type you want to use. This can be either `code` or `token`. For mobile applications using the Implicit Grant Flow this **must be set** to `token` |
| client_id | The Client ID of the Application you registered in Auth0. This can be found on the **Settings** tab of your Application in the Auth0 Dashboard |
-| scope | Specifies the claims (or attributes) of the user you want the be returned in the `id_token`. To obtain an `id_token` you need to specify at least a scope of `openid` (if no scope is specified then `openid` is implied). You can also request other scopes, so for example to return the user's name and profile picture you can request a scope of `openid name picture`.
You can read up more about [scopes](/scopes). |
+| scope | Specifies the claims (or attributes) of the user you want the be returned in the ID Token. To obtain an ID Token you need to specify at least a scope of `openid` (if no scope is specified then `openid` is implied). You can also request other scopes, so for example to return the user's name and profile picture you can request a scope of `openid name picture`.
You can read up more about [scopes](/scopes). |
| redirect_uri | The URL where the user will be redirected to after they have authenticated. For mobile applications you should specify this as `https://${account.namespace}/mobile`|
| connection | This is an optional parameter which allows you to force the user to sign in with a specific connection. You can for example pass a value of `google-oauth2` to send the user directly to Google to log in with their Google account.
If this parameter is not specified the user will be presented with the normal Auth0 Lock screen from where they can sign in with any of the available connections. You can see the list of configured connections on the **Connections** tab of your application. |
| state | The state parameter will be sent back should be used for CSRF and contextual information (like a return url) |
@@ -74,17 +84,17 @@ After the user has authenticated, Auth0 will call back to the URL specified in t
https://${account.namespace}/mobile#id_token=eyJ0...&token_type=Bearer
```
-The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/jwt) containing information about the user. You can extract both of these values from the URL using basic string manipulation techniques in whatever programming language you are using.
+The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/tokens/concepts/jwts) containing information about the user. You can extract both of these values from the URL using basic string manipulation techniques in whatever programming language you are using.
-As mentioned, the `id_token` is a JWT and you will need to decode this token in order to read the claims (or attributes) of the user. The [JWT section of our website](/jwt) contains more information about the structure of a JWT.
+As mentioned, the ID Token is a JWT and you will need to decode this token in order to read the claims (or attributes) of the user. The [JWT section of our website](/tokens/concepts/jwts) contains more information about the structure of a JWT.
-You can also refer to the [libraries section on the JWT.io website](https://jwt.io/#libraries-io) in order to obtain a library for your programming language of choice which will assist you in decoding the `id_token`.
+You can also refer to the [libraries section on the JWT.io website](https://jwt.io/#libraries-io) in order to obtain a library for your programming language of choice which will assist you in decoding the ID Token.
-Once the JWT is decoded, you can extract the information about the user from the Payload of the `id_token`. This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
+Once the JWT is decoded, you can extract the information about the user from the Payload of the ID Token. This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
-### The `id_token` Payload
+### The ID Token Payload
-An example payload for an `id_token` may look something like this:
+An example payload for an ID Token may look something like this:
```json
{
@@ -107,12 +117,12 @@ The payload above contains the following claims:
| email | The email address of the user which is returned from the Identity Provider. |
| picture | The profile picture of the user which is returned from the Identity Provider. |
| sub | The unique identifier of the user. This is guaranteed to be unique per user and will be in the format (identity provider)|(unique id in the provider), such as github|1234567890. |
-| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued `id_token`, this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
-| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued `id_token`, this will be the **Client ID of your Auth0 Application**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued ID Token, this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued ID Token, this will be the **Client ID of your Auth0 Application**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| exp | The _expiration time_. A number representing a specific date and time in the format “seconds since epoch” as [defined by POSIX6](https://en.wikipedia.org/wiki/Unix_time). This claim sets the exact moment from which this **JWT is considered invalid**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| iat | The _issued at time_. A number representing a specific date and time (in the same format as `exp`) at which this **JWT was issued**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
-The exact claims contained in the `id_token` will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an `id_token` issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
+The exact claims contained in the ID Token will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an ID Token issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
::: panel Debugging a JWT
The [JWT.io website](https://jwt.io) has a handy debugger which will allow you to debug any JSON Web Token. This is useful is you quickly want to decode a JWT to see the information contained in the token.
@@ -128,7 +138,7 @@ You can also use this object to store information about the user (such as name,
### A Basic Authentication Request
-The following is the most basic request you can make to the `/authorize` endpoint. It will display the Lock screen and allow a user to sign in with any of the configured connections.
+The following is the most basic request you can make to the `/authorize` endpoint. It will display the Lock screen and allow a user to sign in with any of the configured connections.
```text
https://${account.namespace}/authorize
@@ -145,7 +155,7 @@ https://${account.namespace}/mobile
&token_type=Bearer
```
-And this is an example of the decoded payload of the `id_token` which will be returned:
+And this is an example of the decoded payload of the ID Token which will be returned:
```json
{
@@ -159,7 +169,7 @@ And this is an example of the decoded payload of the `id_token` which will be re
### Request the Name and Profile Picture
-You can request a user's name and profile picture by requesting the `name` and `picture` scopes.
+You can request a user's name and profile picture by requesting the `name` and `picture` scopes.
```text
https://${account.namespace}/authorize
@@ -177,7 +187,7 @@ https://${account.namespace}/mobile
&token_type=Bearer
```
-The name and profile picture will be available in the `name` and `picture` claims of the returned `id_token`:
+The name and profile picture will be available in the `name` and `picture` claims of the returned ID Token:
```json
{
@@ -218,7 +228,7 @@ https://${account.namespace}/mobile
&token_type=Bearer
```
-The user's name and profile picture and email address will be available in the `name`, `picture` and `email` claims of the returned `id_token`. You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
+The user's name and profile picture and email address will be available in the `name`, `picture` and `email` claims of the returned ID Token. You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
```json
{
diff --git a/articles/application-auth/legacy/server-side-web.md b/articles/application-auth/legacy/server-side-web.md
index 01c57db94b..5cb0b0ac58 100644
--- a/articles/application-auth/legacy/server-side-web.md
+++ b/articles/application-auth/legacy/server-side-web.md
@@ -2,6 +2,15 @@
title: Authentication for Server-side Web Apps
description: Explains how to authenticate users in a Server-side Web application.
toc: true
+topics:
+ - oauth2
+ - authentication
+ - server-side-apps
+contentType:
+ - concept
+ - how-to
+useCase:
+ - add-login
---
# Authentication for Server-side Web Apps
@@ -13,7 +22,7 @@ You can use the Auth0 Authentication API to create server-side web applications
## Overview
-Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can redirect the user from your web application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to the `redirect_uri` (also referred to as the Callback URL), returning an `authorization_code` in the query string parameters of the Callback URL. This `authorization_code` can then be exchanged for an `id_token` which contains the identity of the user.
+Auth0 exposes OAuth 2.0 endpoints for authenticating any user. You can redirect the user from your web application to these endpoints in the web browser. Auth0 will handle the authentication of the user, and then redirect the user back to the `redirect_uri` (also referred to as the Callback URL), returning an `authorization_code` in the query string parameters of the Callback URL. This `authorization_code` can then be exchanged for an ID Token which contains the identity of the user.
## The Authentication Flow
@@ -21,9 +30,9 @@ The OAuth 2.0 Authorization Framework allows for different kinds of authorizatio
The Authorization Code flow is initiated by redirecting the user in the web browser to the Auth0 `/authorize` endpoint. Auth0 will then display the Auth0 Lock dialog, allowing the user to enter their credentials or alternatively sign in with any other configured [Identity Provider](/identityproviders).
-After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along an `authorization_code` parameter in the query string of the Callback URL. This code can then be exchanged for an `id_token` by making a request to the `/oauth/token` endpoint.
+After the user has authenticated, Auth0 will redirect the browser back to the **Redirect URI** (also called **Callback URL**), passing along an `authorization_code` parameter in the query string of the Callback URL. This code can then be exchanged for an ID Token by making a request to the `/oauth/token` endpoint.
-The `id_token` is a [JSON Web Token (JWT)](/jwt) and contains various attributes - referred to as _Claims_ - regarding the user, such as the user's name, email address, profile picture and so on.. The `id_token` can be decoded to extract the claims and you are free to use these inside of your application, to display a user's name and profile image for example.
+The ID Token is a [JSON Web Token (JWT)](/tokens/concepts/jwts) and contains various attributes - referred to as _Claims_ - regarding the user, such as the user's name, email address, profile picture and so on.. The ID Token can be decoded to extract the claims and you are free to use these inside of your application, to display a user's name and profile image for example.

@@ -31,7 +40,7 @@ The `id_token` is a [JSON Web Token (JWT)](/jwt) and contains various attributes
2. The user authenticates.
3. The Authorization Server redirects to the `redirect_uri` with an `authorization_code` in the query string.
4. The Application sends the `authorization_code` together with the `redirect_uri` and the Client Id/Client Secret to the Authorization Server.
-5. The Authorization Server validates this information and returns an `id_token`.
+5. The Authorization Server validates this information and returns an ID Token.
## Register your Application
@@ -45,13 +54,13 @@ The **Create Application** window will open, allowing you to enter the name of y
Once the application has been created you can navigate to the **Settings** tab of the application and in the **Allowed Callback URLs** field add a URL where Auth0 must redirect to after the user has authenticated, such as `${account.callback}`.
-This URL must be part of your application, as your application will need to retrieve the `code` and exchange it for the `id_token`.
+This URL must be part of your application, as your application will need to retrieve the `code` and exchange it for the ID Token.

## Call the Authorization URL
-The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any SSO session is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
+The URL used when authenticating a user is `https://${account.namespace}/authorize`. This is the initial endpoint to which a user must be redirected. This will handle checking whether any Single Sign-on (SSO) [session](/sessions) is active, authenticating the user and also potentially redirect the user directly to any Identity Provider to handle authentication.
This endpoint supports the following query string parameters:
@@ -59,7 +68,7 @@ This endpoint supports the following query string parameters:
|:------------------|:---------|
| response_type | The response type specifies the Grant Type you want to use. This can be either `code` or `token`. For server-side web applications using the Authorization Code Flow this **must be set** to `code` |
| client_id | The Client ID of the Application you registered in Auth0. This can be found on the **Settings** tab of your Application in the Auth0 Dashboard |
-| scope | Specifies the claims (or attributes) of the user you want the be returned in the `id_token`. To obtain an `id_token` you need to specify at least a scope of `openid` (if no scope is specified then `openid` is implied). You can also request other scopes, so for example to return the user's name and profile picture you can request a scope of `openid name picture`.
You can read up more about [scopes](/scopes). |
+| scope | Specifies the claims (or attributes) of the user you want the be returned in the ID Token. To obtain an ID Token you need to specify at least a scope of `openid` (if no scope is specified then `openid` is implied). You can also request other scopes, so for example to return the user's name and profile picture you can request a scope of `openid name picture`.
You can read up more about [scopes](/scopes). |
| redirect_uri | The URL in your application where the user will be redirected to after they have authenticated, such as `${account.callback}`|
| connection | This is an optional parameter which allows you to force the user to sign in with a specific connection. You can for example pass a value of `github` to send the user directly to GitHub to log in with their GitHub account.
If this parameter is not specified the user will be presented with the normal Auth0 Lock screen from where they can sign in with any of the available connections. You can see the list of configured connections on the **Connections** tab of your application. |
| state | The state parameter will be sent back should be used for CSRF and contextual information (like a return url) |
@@ -68,7 +77,7 @@ This endpoint supports the following query string parameters:
Be sure to add the **redirect_uri** URL to the list of **Allowed Callback URLs** in the **Settings** tab of your Application inside the [Auth0 Dashboard](${manage_url}).
:::
-## Exhange the `access_code` for an `id_token`
+## Exchange the `access_code` for an ID Token
After the user has authenticated, Auth0 will call back to the URL specified in the `redirect_uri` query string parameter which was passed to the `/authorize` endpoint. When calling back to this URL, Auth0 will pass along an `access_token` in the `code` query string parameter of the URL, such as
@@ -76,18 +85,39 @@ After the user has authenticated, Auth0 will call back to the URL specified in t
${account.callback}?code=2OKj...
```
-You application will need to handle the request to this callback URL, extract the `access_code` from the `code` query string parameter and call the `/oauth/token` endpoint of the Auth0 Authentication API in order to exchange the `access_code` for the `id_token`:
+You application will need to handle the request to this callback URL, extract the `access_code` from the `code` query string parameter and call the `/oauth/token` endpoint of the Auth0 Authentication API in order to exchange the `access_code` for the ID Token:
```har
{
"method": "POST",
"url": "https://${account.namespace}/oauth/token",
"headers": [
- { "name": "Content-Type", "value": "application/json" }
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
],
"postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"client_secret\": \"YOUR_CLIENT_SECRET\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"${account.callback}\"}"
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "https://${account.callback}"
+ }
+ ]
}
}
```
@@ -102,15 +132,15 @@ The response from `/oauth/token` contains an `access_token`, `id_token` and `tok
}
```
-The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/jwt) containing information about the user. You will need to decode the `id_token` in order to read the claims (or attributes) of the user. The [JWT section of our website](/jwt) contains more information about the structure of a JWT.
+The `token_type` will be set to **Bearer** and the `id_token` will be a [JSON Web Token (JWT)](/tokens/concepts/jwts) containing information about the user. You will need to decode the ID Token in order to read the claims (or attributes) of the user. The [JWT section of our website](/tokens/concepts/jwts) contains more information about the structure of a JWT.
-You can refer to the [libraries section on the JWT.io website](https://jwt.io/#libraries-io) in order to obtain a library for your programming language of choice which will assist you in decoding the `id_token`.
+You can refer to the [libraries section on the JWT.io website](https://jwt.io/#libraries-io) in order to obtain a library for your programming language of choice which will assist you in decoding the ID Token.
-Once the JWT is decoded, you can extract the information about the user from the Payload of the `id_token`. This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
+Once the JWT is decoded, you can extract the information about the user from the Payload of the ID Token. This is a JSON structure and will contain the claims (attributes) about the user as well as some other metadata.
-### The `id_token` Payload
+### The ID Token Payload
-An example payload for an `id_token` may look something like this:
+An example payload for an ID Token may look something like this:
```json
{
@@ -133,12 +163,12 @@ The payload above contains the following claims:
| email | The email address of the user which is returned from the Identity Provider. |
| picture | The profile picture of the user which is returned from the Identity Provider. |
| sub | The unique identifier of the user. This is guaranteed to be unique per user and will be in the format (identity provider)|(unique id in the provider), such as github|1234567890. |
-| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued `id_token`, this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
-| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued `id_token`, this will be the **Client ID of your Auth0 Application**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| iss | The _issuer_. A case-sensitive string or URI that uniquely identifies the party that issued the JWT. For an Auth0 issued ID Token, this will be **the URL of your Auth0 tenant**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
+| aud | The _audience_. Either a single case-sensitive string or URI or an array of such values that uniquely identify the intended recipients of this JWT. For an Auth0 issued ID Token, this will be the **Client ID of your Auth0 Application**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| exp | The _expiration time_. A number representing a specific date and time in the format “seconds since epoch” as [defined by POSIX6](https://en.wikipedia.org/wiki/Unix_time). This claim sets the exact moment from which this **JWT is considered invalid**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
| iat | The _issued at time_. A number representing a specific date and time (in the same format as `exp`) at which this **JWT was issued**.
**This is a [registered claim](https://tools.ietf.org/html/rfc7519#section-4.1) according to the JWT Specification** |
-The exact claims contained in the `id_token` will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an `id_token` issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
+The exact claims contained in the ID Token will depend on the `scope` parameter you sent to the `/authorize` endpoint. In an ID Token issued by Auth0, the **registered claims** and the `sub` claim will always be present, but the other claims depends on the `scope`. You can refer to the [examples below](#examples) to see examples of how the scope influences the claims being returned.
::: note
The [JWT.io website](https://jwt.io) has a handy debugger which will allow you to debug any JSON Web Token. This is useful is you quickly want to decode a JWT to see the information contained in the token.
@@ -146,7 +176,7 @@ The [JWT.io website](https://jwt.io) has a handy debugger which will allow you t
### Keep the user logged in
-Auth0 will assist you in authenticating a user, but it is up to you to keep track in your application of whether or not a user is logged in. You can use a cookie or other session storage to keep track of whether a user is logged in or not, and also to store the claims of the user which was extracted from the `id_token`.
+Auth0 will assist you in authenticating a user, but it is up to you to keep track in your application of whether or not a user is logged in. You can use a cookie or other session storage to keep track of whether a user is logged in or not, and also to store the claims of the user which was extracted from the ID Token.
You can then use those claims inside of your application to display the user's information or otherwise personalize the user's experience.
@@ -169,7 +199,7 @@ After the user has authenticated, they will be redirected back to the `redirect_
${account.callback}?code=2OKj...
```
-You can then exchange the `access_code` for an `id_token`. This is an example of the decoded payload of the `id_token` which will be returned:
+You can then exchange the `access_code` for an ID Token. This is an example of the decoded payload of the ID Token which will be returned:
```json
{
@@ -199,7 +229,7 @@ After the user has authenticated, they will be redirected back to the `redirect_
${account.callback}?code=2OKj...
```
-You can then exchange the `access_code` for an `id_token`. The name and profile picture will be available in the `name` and `picture` claims of the returned `id_token`:
+You can then exchange the `access_code` for an ID Token. The name and profile picture will be available in the `name` and `picture` claims of the returned ID Token:
```json
{
@@ -232,7 +262,7 @@ You can just as easily request a user log in with other social providers, like G
- [Social Login using the Authentication API](/api/authentication#social)
:::
-After the user has authenticated, they will be redirected back to the `redirect_uri` with the `id_token` and `token_type` passed as parameters in the hash fragment:
+After the user has authenticated, they will be redirected back to the `redirect_uri` with the ID Token and `token_type` passed as parameters in the hash fragment:
After the user has authenticated, they will be redirected back to the `redirect_uri` with the `access_code` in the `code` query string parameter:
@@ -240,7 +270,7 @@ After the user has authenticated, they will be redirected back to the `redirect_
${account.callback}?code=2OKj...
```
-You can then exchange the `access_code` for an `id_token`. The user's name and profile picture and email address will be available in the `name`, `picture` and `email` claims of the returned `id_token`. You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
+You can then exchange the `access_code` for an ID Token. The user's name and profile picture and email address will be available in the `name`, `picture` and `email` claims of the returned ID Token. You will also notice that the `sub` claim contains the User's unique ID returned from GitHub:
```json
{
diff --git a/articles/applications/addons.md b/articles/applications/addons.md
deleted file mode 100644
index e9a5612132..0000000000
--- a/articles/applications/addons.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-description: Explains what Add-ons are and how they are associated with Auth0 Applications.
----
-
-# Application Add-ons
-
-Add-ons are plugins associated with an application in Auth0. Usually, they are third-party APIs used by the application(s) that Auth0 generates Access Tokens for (for example, Salesforce, Azure Service Bus, Azure Mobile Services, SAP and more).
-
-To view all the available add-ons for an application navigate to [Dashboard > Applications > Addons](${manage_url}/#/applications/${account.clientId}/addons).
-
-
-
-Some typical scenarios for using add-ons include:
-
-* **Accessing External APIs**: Using the Delegation endpoint, you can exchange an application's Access Token for a third-party service's (such as Salesforce or Amazon) Access Token.
-
-* **Integrating with Applications Using SAML2/WS-Federation**: Add-ons allow you to integrate with any custom or SSO integration that does not currently enjoy built-in Auth0 support, since they allow you to configure every aspect of the SAML2/WS-Federation integration.
-
-
diff --git a/articles/applications/application-grant-types.md b/articles/applications/application-grant-types.md
deleted file mode 100644
index eda69f9382..0000000000
--- a/articles/applications/application-grant-types.md
+++ /dev/null
@@ -1,178 +0,0 @@
----
-description: Using the Grant Types property on Applications
-toc: true
----
-# Application Grant Types
-
-Auth0 provides many different authentication and authorization flows to suit your needs. For example, if you are securing a mobile app, you'd use the [Authorization Code using Proof Key for Code Exchange (PKCE) OAuth 2.0 Grant](/api-auth/grant/authorization-code-pkce), or if you're securing a client-side app (such as a mobile app that's *not* native), you'd use the [Implicit Grant](api-auth/grant/implicit).
-
-However, you might want to limit the use of certain flows (which we'll refer to as "grant types" in this doc) depending on the type of app you're securing. You can set and manage these limitations using the `grant_types` property that each Client has.
-
-In this doc, we'll talk about:
-
-* What grant types are
-* The grant types available
-* How to set the Client's `grant_type` property
-* What grant types are available based on the Client's `grant_type` property value
-
-## What Grant Types Are
-
-OAuth 2.0 is a protocol that allows you to grant limited access to your resources to another entity without exposing credentials. By using Auth0, you can support different OAuth 2.0 flows without worrying about the technical aspects/implementation.
-
-OAuth 2.0 supports several types of grants, which are methods by which you can gain Access Tokens (string values that represent the permissions granted). Different grant types allow different types of access, and based on the needs of your app, some grant types are more appropriate than others. Auth0 allows you to indicate which sets of permissions are appropriate based on the `grant_type` property.
-
-::: note
-Not sure which non-legacy grant type is appropriate for your use case? Refer to [Which OAuth 2.0 flow should I use?](/api-auth/which-oauth-flow-to-use) for help.
-:::
-
-## Grant Types Available
-
-The following is a list of grant types valid for Auth0 Applications. The grant types can be divided into three different categories:
-
-* Grants that conform with specifications (such as [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html))
-* [Auth0 extension grants](https://tools.ietf.org/html/rfc6749#section-4.5)
-* Auth0 legacy grants
-
-The following `grant_types`, are either:
-
-* OIDC-conformant (that is, their implementation conforms to the [OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html))
-* Auth0 extension grants
-
-| `grant_type` | More info |
-|:-----|:----|
-| `implicit` | [Implicit Grant](/api-auth/grant/implicit) |
-| `authorization_code` | [Authorization Code Grant](/api-auth/grant/authorization-code) |
-| `client_credentials` | [Client Credentials Grant](/api-auth/grant/client-credentials) |
-| `password` | [Resource Owner Password Grant](/api-auth/grant/password) |
-| `refresh_token` | [Use a Refresh Token](/tokens/refresh-token/current#use-a-refresh-token) |
-| `http://auth0.com/oauth/grant-type/password-realm` | [Use an extension grant similar to the Resource Owner Password Grant that includes the ability to indicate a specific realm](/api-auth/grant/password#realm-support) |
-| `http://auth0.com/oauth/grant-type/mfa-oob` | [Multifactor Authentication OOB Grant Request](/api-auth/tutorials/multifactor-resource-owner-password#mfa-oob-grant-request) |
-| `http://auth0.com/oauth/grant-type/mfa-otp` | [Multifactor Authentication OTP Grant Request](/api-auth/tutorials/multifactor-resource-owner-password#mfa-otp-grant-request) |
-| `http://auth0.com/oauth/grant-type/mfa-recovery-code` | [Multifactor Authentication Recovery Grant Request](/api-auth/tutorials/multifactor-resource-owner-password#mfa-recovery-grant-request) |
-
-The following are legacy grant types:
-
-* `http://auth0.com/oauth/legacy/grant-type/ro`
-* `http://auth0.com/oauth/legacy/grant-type/ro/jwt-bearer`
-* `http://auth0.com/oauth/legacy/grant-type/delegation/refresh_token`
-* `http://auth0.com/oauth/legacy/grant-type/delegation/id_token`
-* `http://auth0.com/oauth/legacy/grant-type/access_token`
-
-## How to Edit the Client `grant_types` Property
-
-You can set the the `grant_types` property for your Auth0 Client using the Management Dashboard.
-
-::: warning
-As of 8 June 2017, new Auth0 customers **cannot** add *any* of the legacy grant types to their Applications. Only customers as of 8 June 2017 can add legacy grant types to their existing Applications.
-:::
-
-Begin by navigating to the [Applications page](${manage_url}/#/applications) of the Management Dashboard.
-
-
-
-Click on the cog icon next to the Client you're interested in to launch its settings page.
-
-
-
-Scroll down to the bottom of the settings page, and click **Advanced Settings**.
-
-
-
-Switch to the **Grant Types** tab and enable or disable the respective grants for this client. Click **Save Changes**.
-
-
-
-### Use the Management API
-
-In addition to setting the `grant_types` value using the Dasbhoard, you can make a [`PATCH` call to the Update a Client endpoint](/api/management/v2#!/Clients/patch_applications_by_id) of the Management API to update the `grant_types` field.
-
-### Errors
-
-Attempting to use any flow with a client lacking the appropriate `grant_types` for that flow (or with the field empty) will result in the following error:
-
-```text
-Grant type `grant_type` not allowed for the client.
-```
-
-## Information for Existing and New Auth0 Customers
-
-As of 8 June 2017, all Auth0 applications have a `grant_types` property that **must** be populated. Here's how Auth0 will handle this change based on whether you're a current customer with an existing Client or a new customer.
-
-### Existing Applications
-
-To avoid changes in functionality for current Auth0 customers, we will populate the `grant_types` property for all existing Applications as of 8 June 2017 with **all** Auth0 legacy, Auth0 extension, and specification-conformant grant types.
-
-### New Applications
-
-Depending on whether a newly-created Client is [public](/applications/client-types#public-applications) or [confidential](/applications/client-types#confidential-applications), the Client will have varying access to grant types. Trusted first-party applications have access to additional grant types.
-
-#### Public Applications
-
-Public Applications, indicated by the `token_endpoint_auth_method` flag set to `none`, are those created in the Dashboard for Native and Single Page Applications.
-
-::: panel Token Endpoint Authentication Method
-The `Token Endpoint Authentication Method` defines how a client authenticates against the [token endpoint](/api/authentication#authorization-code). Its valid values are:
-
-* `None`, for a public client without a client secret
-* `Post`, for a client using HTTP POST parameters
-* `Basic`, for a client using HTTP Basic parameters
-
-You can find this field at the [Client Settings page](${manage_url}/#/applications/${account.clientId}/settings) of the [Auth0 Dashboard](${manage_url}).
-:::
-
-By default, Public Applications are created with the following `grant_types`:
-
-* `implicit`
-* `authorization_code`
-* `refresh_token`
-
-::: note
-Public applications **cannot** utilize the `client_credentials` grant type. To add this grant type to a Client using the [Management API](/api/management/v2#!/Clients/patch_clients_by_id), set the **token_endpoint_auth_method** to `client_secret_post` or `client_secret_basic`. Either of these will indicate the Client is confidential, not public.
-:::
-
-#### Confidential Applications
-
-Confidential Applications, indicated by the `token_endpoint_auth_method` flag set to anything *except* `none`, are those created in the Dashboard for Regular Web Applications or Non-Interactive Applications. Additionally, any Client where `token_endpoint_auth_method` is unspecified is confidential. By default, Confidential Applications are created with the following `grant_types`:
-
-* `implicit`;
-* `authorization_code`;
-* `refresh_token`;
-* `client_credentials`.
-
-#### Trusted First-Party Applications
-
-Trusted first-party applications can additionally use the following `grant_types`:
-
-* `password`
-* `http://auth0.com/oauth/grant-type/password-realm`
-* `http://auth0.com/oauth/grant-type/mfa-oob`
-* `http://auth0.com/oauth/grant-type/mfa-otp`
-* `http://auth0.com/oauth/grant-type/mfa-recovery-code`
-
-::: note
-If you are using the [Dashboard](${manage_url}) to enable or disable these grant types, note that all the Password and MFA grant types are enabled when you add the `Password` or `MFA` grant type on your client. You cannot select these individually.
-:::
-
-## Secure Alternatives to the Legacy Grant Types
-
-If you're currently using a legacy grant type, refer to the chart below to see which of the secure alternatives you should use instead.
-
-| Legacy Grant Type | Alternative |
-|:-----|:----|
-|`http://auth0.com/oauth/legacy/grant-type/ro` | Use the [/oauth/token](/api/authentication#authorization-code) endpoint with a grant type of `password`. See [Resource Owner Password Credentials Exchange](/api-auth/tutorials/adoption/password) and [Executing the Resource Owner Password Grant](/api-auth/tutorials/password-grant) for additional information. |
-| `http://auth0.com/oauth/legacy/grant-type/ro/jwt-bearer` | This feature is disabled by default. If you would like this feature enabled, please [contact support](https://support.auth0.com/) to discuss your use case and prevent the possibility of introducing security vulnerabilities. |
-| `http://auth0.com/oauth/legacy/grant-type/delegation/refresh_token` | Use the `oauth/token` endpoint to obtain Refresh Tokens. See [OIDC-conformant Refresh Tokens](/api-auth/tutorials/adoption/refresh-tokens) for more info. |
-| `http://auth0.com/oauth/legacy/grant-type/delegation/id_token` | This feature is disabled by default. If you would like this feature enabled, please [contact support](https://support.auth0.com/) to discuss your use case and prevent the possibility of introducing security vulnerabilities. |
-| `http://auth0.com/oauth/legacy/grant-type/access_token` | Use browser-based social authentication. |
-
-::: note
-Those implementing Passwordless Authentication should use [universal login](/hosted-pages/login) instead of the `oauth/ro` endpoint.
-:::
-
-## Enable a Legacy Grant Type
-
-::: warning
-As of 8 June 2017, new Auth0 customers cannot add any of the legacy grant types to their applications. Legacy grant types are only available for previous customers while they migrate to new flows, to avoid breaking changes. To find the secure alternative for your case refer to [Secure Alternatives to the Legacy Grant Types](#secure-alternatives-to-the-legacy-grant-types).
-:::
-
-To enable a legacy grant type, you will need to update the `grant_types` property for you client appropriately. For details on how to do so, refer to [Edit the grant_types Property](#edit-available-grant_types).
diff --git a/articles/applications/application-settings/_adv-settings-mobile.md b/articles/applications/application-settings/_adv-settings-mobile.md
new file mode 100644
index 0000000000..fb14954545
--- /dev/null
+++ b/articles/applications/application-settings/_adv-settings-mobile.md
@@ -0,0 +1,8 @@
+
+#### Device Settings
+
+If you're developing a mobile application, you can provide the necessary iOS/Android parameters here.
+
+When developing iOS apps, you'll provide your **Team ID** and **App Bundle Identifier**.
+
+When developing Android apps, you'll provide your **App Package Name** and your **Key Hashes**.
diff --git a/articles/applications/application-settings/_adv-settings.md b/articles/applications/application-settings/_adv-settings.md
index d2af38f64d..f86aa43c4a 100644
--- a/articles/applications/application-settings/_adv-settings.md
+++ b/articles/applications/application-settings/_adv-settings.md
@@ -14,19 +14,11 @@ Application metadata are custom string keys and values (each of which has a char
You can create up to 10 sets of metadata.
-#### Mobile Settings
-
-If you're developing a mobile application, you can provide the necessary iOS/Android parameters here.
-
-When developing iOS apps, you'll provide your **Team ID** and **App Bundle Identifier**.
-
-When developing Android apps, you'll provide your **App Package Name** and your **Key Hashes**.
-
#### OAuth
Set the OAuth-related settings on this tab:
-* By default, all apps/APIs can make a delegation request, but if you want to explicitly grant permissions to selected apps/APIs, you can do so in **Allowed APPs/APIs**.
+* By default, all apps/APIs can make a delegation request, but if you want to explicitly grant permissions to selected apps/APIs, you can do so in **Allowed Apps/APIs**.
* Set the algorithm used (**HS256** or **RS256**) for signing your JSON Web Tokens.
diff --git a/articles/applications/application-settings/_settings-pt2.md b/articles/applications/application-settings/_settings-pt2.md
index 1fcc3b475d..cbd497d7b3 100644
--- a/articles/applications/application-settings/_settings-pt2.md
+++ b/articles/applications/application-settings/_settings-pt2.md
@@ -1,15 +1,17 @@
-
+::: note
+You can provide up to 100 URLs in the **Allowed Callback URLs**, **Allowed Web Origins**, **Allowed Logout URLs**, **Allowed Origins (CORS)** fields.
+:::
-- **Allowed Callback URLs**: Set of URLs to which Auth0 is allowed to redirect the users after they authenticate. You can specify multiple valid URLs by comma-separating them (typically to handle different environments like QA or testing). You can use the star symbol as a wildcard for subdomains (`*.google.com`). Make sure to specify the protocol, `http://` or `https://`, otherwise the callback may fail in some cases.
+- **Allowed Callback URLs**: Set of URLs to which Auth0 is allowed to redirect the users after they authenticate. You can specify multiple valid URLs by comma-separating them (typically to handle different environments like QA or testing). For production environments, verify that the URLs do not point to localhost. You can use the star symbol as a wildcard for subdomains (`*.google.com`). Make sure to specify the protocol, `http://` or `https://`, otherwise the callback may fail in some cases.
-- **Allowed Web Origins**: List of URLs from where an authorization request, using [`web_message` as the response mode](/protocols/oauth2#how-response-mode-works), can originate from. You can specify multiple valid URLs by comma-separating them.
+- **Allowed Web Origins**: List of URLs from where an authorization request, using [`web_message` as the response mode](/protocols/oauth2#how-response-mode-works), can originate from. You can specify multiple valid URLs by comma-separating them. For production environments, verify that the URLs do not point to localhost.
-- **Allowed Logout URLs**: After a user logs out from Auth0 you can redirect them with the `returnTo` query parameter. The URL that you use in `returnTo` must be listed here. You can specify multiple valid URLs by comma-separating them. You can use the star symbol as a wildcard for subdomains (`*.google.com`). Notice that querystrings and hash information are not taken into account when validating these URLs. Read more about this at: [Logout](/logout).
+- **Allowed Logout URLs**: After a user logs out from Auth0 you can redirect them with the `returnTo` query parameter. The URL that you use in `returnTo` must be listed here. You can specify multiple valid URLs by comma-separating them. For production environments, verify that the URLs do not point to localhost. You can use the star symbol as a wildcard for subdomains (`*.google.com`). Notice that querystrings and hash information are not taken into account when validating these URLs. Read more about this at: [Logout](/logout).
-- **Allowed Origins (CORS)**: Set of URLs that will be allowed to make requests from JavaScript to Auth0 API (typically used with CORS). This prevents same-origin policy errors when using Auth0 from within a web browser. By default, all your callback URLs will be allowed. This field allows you to enter other origins if you need to. You can specify multiple valid URLs by comma-separating them. You can use the star symbol as a wildcard for subdomains (`*.google.com`). Notice that paths, querystrings and hash information are not taken into account when validating these URLs (and may, in fact, cause the match to fail).
+- **Allowed Origins (CORS)**: Set of URLs that will be allowed to make requests from JavaScript to Auth0 API (typically used with CORS). This prevents same-origin policy errors when using Auth0 from within a web browser. By default, all your callback URLs will be allowed. This field allows you to enter other origins if you need to. You can specify multiple valid URLs by comma-separating them. For production environments, verify that the URLs do not point to localhost. You can use the star symbol as a wildcard for subdomains (`*.google.com`). Notice that paths, querystrings and hash information are not taken into account when validating these URLs (and may, in fact, cause the match to fail).
-- **JWT Expiration (seconds)**: The amount of time (in seconds) before the Auth0 id_token expires. The default value is `36000`, which maps to 10 hours.
+- **ID Token Expiration (seconds)**: The amount of time (in seconds) before the Auth0 ID Token expires. The default value is `36000` seconds which is 10 hours.
-- **Use Auth0 instead of the IdP to do Single Sign On**: If enabled, this setting prevents Auth0 from redirecting authenticated users with valid sessions to the identity provider (such as Facebook, ADFS, and so on).
+- **Use Auth0 instead of the IdP to do Single Sign-on**: If enabled, this setting prevents Auth0 from redirecting authenticated users with valid [sessions](/sessions) to the identity provider (such as Facebook, ADFS, and so on). **Legacy tenants only.**

diff --git a/articles/applications/application-settings/_settings.md b/articles/applications/application-settings/_settings.md
index 596a1350fb..7a276d13d1 100644
--- a/articles/applications/application-settings/_settings.md
+++ b/articles/applications/application-settings/_settings.md
@@ -6,7 +6,7 @@
- **Client ID**: The unique identifier for your application. This is the ID you will use with when configuring authentication with Auth0. It is generated by the system when you create a new application and it cannot be modified.
-- **Client Secret**: A string used to sign and validate `id_tokens` for authentication flows and to gain access to select Auth0 API endpoints. By default, the value is hidden, so check the **Reveal Client Secret** box to see this value.
+- **Client Secret**: A string used to sign and validate ID Tokens for authentication flows and to gain access to select Auth0 API endpoints. By default, the value is hidden, so check the **Reveal Client Secret** box to see this value.
::: warning
While the Client ID is considered public information, the Client Secret **must be kept confidential**. If anyone can access your Client Secret they can issue tokens and access resources they shouldn't.
diff --git a/articles/applications/application-settings/index.yml b/articles/applications/application-settings/index.yml
deleted file mode 100644
index 12753dbc99..0000000000
--- a/articles/applications/application-settings/index.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-versioning:
- baseUrl: applications/application-settings
- current: native
- versions:
- - native
- - single-page-app
- - regular-web-app
- - non-interactive
- defaultArticles:
- native: index
- single-page-app: index
- regular-web-app: index
- non-interactive: index
diff --git a/articles/applications/application-settings/native/index.md b/articles/applications/application-settings/native/index.md
deleted file mode 100644
index 0803ec041d..0000000000
--- a/articles/applications/application-settings/native/index.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-description: Application settings for Native
-url: /applications/application-settings/native
-toc: true
----
-
-# Application Settings: Native
-
-::: version-warning
-This document lists the settings for a Native Application; if you're using a different Application type, please use the drop-down to select the appropriate doc.
-:::
-
-When creating an Auth0 Application, you'll be asked to indicate the *type* of Application you want to create.
-
-
-
-For desktop or mobile apps running natively on the device, you'll want to create a Native Application.
-
-## Settings
-
-<%= include('../_settings') %>
-
-- **Application Type**: The type of application you are implementing. For desktop or mobile apps running natively on the device, you'll want to create a Native Application.
-
-<%= include('../_settings-pt2') %>
-
-### Advanced Settings
-
-<%= include('../_adv-settings') %>
-
-<%= include('../_adv-settings-pt2') %>
diff --git a/articles/applications/application-settings/non-interactive/index.md b/articles/applications/application-settings/non-interactive/index.md
deleted file mode 100644
index 85f4277e9a..0000000000
--- a/articles/applications/application-settings/non-interactive/index.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-description: Application settings for Machine to Machine Applications
-url: /applications/application-settings/non-interactive
-toc: true
----
-
-# Application Settings: Machine to Machine Application
-
-::: version-warning
-This document lists the settings for a Machine to Machine Application; if you're using a different Application type, please use the drop-down to select the appropriate doc.
-:::
-
-When creating an Auth0 Application, you'll be asked to indicate the *type* of Application you want to create.
-
-
-
-If your app is a CLI, daemon, or a service running on the backend, you'll want to create a **Machine to Machine Application**.
-
-## Settings
-
-<%= include('../_settings') %>
-
-- **Application Type**: The type of application you are implementing. If your app is a CLI, daemon, or a service running on the backend, use a **Machine to Machine Application**.
-
-<%= include('../_token-endpoint-auth-method') %>
-
-<%= include('../_settings-pt2') %>
-
-### Advanced Settings
-
-<%= include('../_adv-settings') %>
-
-<%= include('../_trust-token-endpoint-ip-header') %>
-
-<%= include('../_adv-settings-pt2') %>
diff --git a/articles/applications/application-settings/regular-web-app/index.md b/articles/applications/application-settings/regular-web-app/index.md
deleted file mode 100644
index aaf78fbb2c..0000000000
--- a/articles/applications/application-settings/regular-web-app/index.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-description: Application settings for Web Apps
-url: /applications/application-settings/regular-web-app
-toc: true
----
-# Application Settings: Regular Web Applications
-
-::: version-warning
-This document lists the settings for a Regular Web App; if you're using a different Application type, please use the drop-down to select the appropriate doc.
-:::
-
-When creating an Auth0 Application, you'll be asked to indicate the *type* of Application you want to create.
-
-
-
-If you're working with a traditional web app that has the ability to refresh its pages, you'll want to create a Regular Web Application.
-
-## Settings
-
-<%= include('../_settings') %>
-
-- **Application Type**: The type of application you are implementing. If you're working with a traditional web app that has the ability to refresh its pages, use a Regular Web Applications.
-
-<%= include('../_token-endpoint-auth-method') %>
-
-<%= include('../_settings-pt2') %>
-
-### Advanced Settings
-
-<%= include('../_adv-settings') %>
-
-<%= include('../_trust-token-endpoint-ip-header') %>
-
-<%= include('../_adv-settings-pt2') %>
diff --git a/articles/applications/application-settings/single-page-app/index.md b/articles/applications/application-settings/single-page-app/index.md
deleted file mode 100644
index 2d75ebb05f..0000000000
--- a/articles/applications/application-settings/single-page-app/index.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-description: Application settings for Single Page Apps
-url: /applications/application-settings/single-page-app
-toc: true
----
-
-# Application Settings: Single Page Applications
-
-::: version-warning
-This document lists the settings for an SPA Application; if you're using a different Application type, please use the drop-down to select the appropriate doc.
-:::
-
-When creating an Auth0 Application, you'll be asked to indicate the *type* of Application you want to create.
-
-
-
-If your app is similar to one with a JavaScript front-end that utilizes an API, you'll want to create a SPA Application.
-
-## Settings
-
-<%= include('../_settings') %>
-
-- **Application Type**: The type of application you are implementing. For apps with a JavaScript front-end that utilizes an API, create an SPA.
-
-<%= include('../_settings-pt2') %>
-
-### Advanced Settings
-
-<%= include('../_adv-settings') %>
-
-<%= include('../_adv-settings-pt2') %>
diff --git a/articles/applications/application-types.md b/articles/applications/application-types.md
deleted file mode 100644
index 187bd858cf..0000000000
--- a/articles/applications/application-types.md
+++ /dev/null
@@ -1,102 +0,0 @@
----
-title: Application Types
-description: Read about the the different applications types: public vs confidential, and first vs third-party
-toc: true
----
-# Application Types
-
-<%= include('../_includes/_pipeline2') %>
-
-When working with Auth0 applications, which are used to represent your applications, there are several terms you should know in terms of how applications are classified:
-
-* [Confidential vs public](#confidential-vs-public-applications)
-* [First vs third-party](#first-vs-third-party-applications)
-
-## Confidential vs public applications
-
-The OAuth 2.0 specification [defines two types of applications](https://tools.ietf.org/html/rfc6749#section-2.1): public and confidential.
-
-When creating an application through the [Dashboard](${manage_url}/#/applications), Auth0 will ask you what type of application you want the application to represent and use that information to determine the application type.
-
-### Check your application type
-
-You can use the Management API's [Get a Client endpoint](/api/management/v2#!/Clients/get_clients_by_id) to check your existing Application's type. If the application is first party, the `is_first_party` equals `true`, else `false`. Be sure to replace `CLIENT_ID` with the ID of your application.
-
-```har
-{
- "method": "GET",
- "url": "https://${account.namespace}/api/v2/clients/CLIENT_ID?fields=is_first_party&include_fields=true",
- "headers": [{
- "name": "Authorization",
- "value": "Bearer MGMT_API_ACCESS_TOKEN"
- }]
-}
-```
-
-::: note
-See [The Auth0 Management APIv2 Token](/api/management/v2/tokens) for instructions on obtaining the Access Token required to call the Management API.
-:::
-
-### Confidential applications
-
-Confidential applications are able to hold credentials (such as a client ID and secret) in a secure way without exposing them to unauthorized parties. This means that you will need a trusted backend server to store the secret(s).
-
-The following application types use confidential applications:
-
-* A web application with a secure backend using the [Authorization Code grant](/api-auth/grant/authorization-code), [Password](/api-auth/grant/password) or [Password Realm](/api-auth/tutorials/password-grant#realm-support) grants
-* A machine to machine application using the [Client Credentials grant](/api-auth/grant/client-credentials)
-
-All of these grants require applications to authenticate by specifying their client ID and secret when calling the token endpoint.
-
-Since confidential applications are capable of holding secrets, you can choose to have ID Tokens issued to them that have been signed in one of two ways:
-
-* Symmetrically using their client secret (`HS256`)
-* Asymmetrically using a private key (`RS256`)
-
-### Public applications
-
-Public applications **cannot** hold credentials securely. The following application types use public applications:
-
-* Native desktop or mobile applications using the [Authorization Code grant with PKCE](/api-auth/grant/authorization-code-pkce)
-* JavaScript-based client-side web applications (such as single-page apps) using the [Implicit](/api-auth/grant/implicit) grant
-
-Since public applications are unable to hold secrets, [ID Tokens](/tokens/id-token) issued to them must be:
-
-* Signed asymmetrically using a private key (`RS256`)
-* Verified using the public key corresponding to the private key used to sign the token
-
-## First vs third-party applications
-
-First-party and third-party refer to the ownership of the application. This has implications in terms of who has administrative access to your Auth0 domain.
-
-### First-party applications
-
-First-party applications are those controlled by the same organization or person who owns the Auth0 domain. For example, if you wanted to access the Contoso API, you'd use a first-party applications to log into `contoso.com`.
-
-All applications created via the [Dashboard](${manage_url}/#/applications) are first-party by default.
-
-### Third-party applications
-
-Third-party applications are controlled by someone who most likely should *not* have administrative access to your Auth0 domain. Third-party applications enable external parties or partners to access protected resources behind your API securely. For example, if you were to create a developer center that allows users to obtain credentials to integrate their apps with your API (this functionality is similar to those provided by well-known APIs such as Facebook, Twitter, and GitHub), you would use a third-party applications.
-
-Third-party applications must be created through the [Management API](/api/management/v2#!/Clients/post_clients) by setting `is_first_party` to `false`.
-
-Third party applications have the following characteristics:
-
-- They cannot skip user consent when consuming APIs. This is for security purposes, as anyone can create an applications, but each applications relies on the final user to provide consent.
-- The [ID Tokens](/tokens/id-token) generated for these applications, hold minimum user profile information.
-- They can use only tenant level connections (domain connections). These are sources of users, configured in the tenant's [dashboard](${manage_url}) as connections. These connections are enabled for every third party applications and can be also enabled for selected first party (standard) applications.
-- To authenticate users using [Lock](/libraries/lock), you will have to use a version greater than `10.7`.
- - [PSaaS Appliance](/appliance) users must use `https://{config.auth0Domain}/` as the value for [the `configurationBaseUrl` option](https://github.com/auth0/lock#other-options).
-- They cannot use [ID Tokens](/tokens/id-token) to invoke [Management APIv2](/api/management/v2) endpoints. Instead, they should get a Management APIv2 Token (see the *How to get a Management APIv2 Token* panel for details). Note that the applications should be granted the `current_user_*` scopes, as required by each endpoint.
- - `read:current_user`: [List or search users](/api/management/v2#!/Users/get_users), [Get a user](/api/management/v2#!/Users/get_users_by_id), [Get user Guardian enrollments](/api/management/v2#!/Users/get_enrollments)
- - `update:current_user_metadata`: [Update a user](/api/management/v2#!/Users/patch_users_by_id), [Delete a user's multifactor provider](/api/management/v2#!/Users/delete_multifactor_by_provider)
- - `create:current_user_device_credentials`: [Create a device public key](/api/management/v2#!/Device_Credentials/post_device_credentials)
- - `delete:current_user_device_credentials`: [Delete a device credential](/api/management/v2#!/Device_Credentials/delete_device_credentials_by_id)
- - `update:current_user_identities`: [Link a user account](/api/management/v2#!/Users/post_identities), [Unlink a user identity](/api/management/v2#!/Users/delete_provider_by_user_id)
-
-::: panel How to get a Management APIv2 Token
-In order to access the [Management APIv2](/api/management/v2) endpoints from a third party applications, you need a Management APIv2 Token. To get one you can use any of the [API Authorization Flows](/api-auth), with the following request parameters:
-- `audience=https://${account.namespace}/api/v2/`
-- `scope=read:current_user update:current_user_metadata`
-:::
diff --git a/articles/applications/concepts/app-types-confidential-public.md b/articles/applications/concepts/app-types-confidential-public.md
new file mode 100644
index 0000000000..8a5e97d787
--- /dev/null
+++ b/articles/applications/concepts/app-types-confidential-public.md
@@ -0,0 +1,63 @@
+---
+description: Understand the difference between confidential and public application types.
+toc: true
+topics:
+ - applications
+ - application-types
+contentType: concept
+useCase:
+ - build-an-app
+---
+# Confidential and Public Applications
+
+According to the [OAuth 2.0 spec](https://tools.ietf.org/html/rfc6749#section-2.1), applications can be classified as either confidential or public. The main difference relates to whether or not the application is able to hold credentials (such as a client ID and secret) securely.
+
+When you create an application using the Dashboard, Auth0 will ask you what [Auth0 application type](/applications) you want to assign to the new application and use that information to determine whether the application is confidential or public.
+
+To check whether your application is confidential or public, see [View Application Type: Confidential or Public](/dashboard/guides/applications/view-app-type-confidential-public).
+
+## Confidential applications
+
+Confidential applications can hold credentials in a secure way without exposing them to unauthorized parties. They require a trusted backend server to store the secret(s).
+
+### Grant types
+
+Because they use a trusted backend server, confidential applications can use grant types that require them to authenticate by specifying their client ID and secret when calling the token endpoint.
+
+The following are considered to be confidential applications:
+
+* A web application with a secure backend that uses the [Authorization Code Flow](/flows/concepts/auth-code), [Password grant](/api-auth/grant/password), or [Password grant with Realm support](/api-auth/tutorials/password-grant#realm-support)
+* A machine-to-machine (M2M) application that uses the [Client Credentials Flow](/flows/concepts/client-credentials)
+
+### ID Tokens
+
+Because confidential applications are capable of holding secrets, you can have ID Tokens issued to them that have been signed in one of two ways:
+
+* Symmetrically, using their client secret (`HS256`)
+* Asymmetrically, using a private key (`RS256`)
+
+## Public applications
+
+Public applications **cannot** hold credentials securely.
+
+### Grant types
+
+Public applications can only use grant types that do not require the use of their client secret.
+
+The following are public applications:
+
+* A native desktop or mobile application that uses the [Authorization Code Flow with PKCE](/flows/concepts/auth-code-pkce)
+* A JavaScript-based client-side web application (such as a single-page app) that uses the [Implicit Flow](/flows/concepts/implicit) grant
+
+### ID Tokens
+
+Because public applications are unable to hold secrets, [ID Tokens](/tokens/concepts/id-tokens) issued to them must be:
+
+* Signed asymmetrically using a private key (`RS256`)
+* Verified using the public key corresponding to the private key used to sign the token
+
+## Keep reading
+
+* [View Application Type](/dashboard/guides/applications/view-app-type-confidential-public)
+* [First-Party and Third-Party Applications](/applications/concepts/app-types-first-third-party)
+* [Auth0 Grant Types Mapping](/applications/reference/grant-types-auth0-mapping)
diff --git a/articles/applications/concepts/app-types-first-third-party.md b/articles/applications/concepts/app-types-first-third-party.md
new file mode 100644
index 0000000000..1412c22625
--- /dev/null
+++ b/articles/applications/concepts/app-types-first-third-party.md
@@ -0,0 +1,43 @@
+---
+description: Understand the difference between confidential and public application types.
+topics:
+ - applications
+ - application-types
+contentType: concept
+useCase:
+ - build-an-app
+---
+# First-Party and Third-Party Applications
+
+Applications can be classified as either first-party or third-party, which refers to the ownership of the application. The main difference relates to who has administrative access to your Auth0 domain.
+
+## First-party applications
+
+First-party applications are those controlled by the same organization or person who owns the Auth0 domain. For example, let's say you created both a Contoso API and an application that logs into `contoso.com` and consumes the Contoso API. You would register both the API and application under the same Auth0 domain, and the application would be a first-party application. By default, all applications created via the [Auth0 Dashboard](${manage_url}/#/applications) are first-party applications.
+
+## Third-party applications
+
+Third-party applications are controlled by someone who most likely should *not* have administrative access to your Auth0 domain. Third-party applications enable external parties or partners to securely access protected resources behind your API. An example of this is with Facebook, let's say you created an application to get a client ID and secret to integrate with your service. That application is considered third-party because it is not owned by Facebook but a third-party that wants to integrate with Facebook APIs and services.
+
+::: note
+All applications created through [Dynamic Client Registration](/api-auth/dynamic-client-registration) will be third-party.
+
+Third-party applications cannot be created using the Dashboard, but must be created through the [Auth0 Management API](/api/management/v2#!/Clients/post_clients) by setting `is_first_party` to `false`.
+:::
+
+Third-party applications have the following unique characteristics:
+
+- **User Consent**: You must require user consent when consuming APIs because anyone can create an application. Requiring the user to provide consent improves security.
+
+- **ID Tokens**: [ID Tokens](/tokens/concepts/id-tokens) generated for third-party applications hold only minimum user profile information.
+
+- **Connections**: You can only use tenant-level connections or *domain connections*. For more informations, see [Enable Third-party Applications](/applications/guides/enable-third-party-apps).
+
+## Keep reading
+
+* [View Application Ownership](/api/management/guides/applications/view-ownership)
+* [Applications](/applications)
+* [Confidential and Public Applications](/applications/concepts/app-types-confidential-public)
+* [Auth0 Grant Types Mapping](/applications/reference/grant-types-auth0-mapping)
+* [User consent and third-party applications](/api-auth/user-consent)
+
\ No newline at end of file
diff --git a/articles/applications/concepts/application-grant-types.md b/articles/applications/concepts/application-grant-types.md
new file mode 100644
index 0000000000..76ced1103e
--- /dev/null
+++ b/articles/applications/concepts/application-grant-types.md
@@ -0,0 +1,32 @@
+---
+title: Application Grant Types
+description: Learn about the concept of grant types and how they relate to applications.
+topics:
+ - applications
+ - grant-types
+contentType:
+ - concept
+useCase:
+ - build-an-app
+---
+# Application Grant Types
+
+Application grant types (or _flows_) are methods through which applications can gain [Access Tokens](/tokens/concepts/access-tokens) and by which you grant limited access to your resources to another entity without exposing credentials. The [OAuth 2.0 protocol](/protocols/oauth2) supports several types of grants, which allow different types of access.
+
+Based on the needs of your application, some grant types are more appropriate than others. Auth0 provides many different authentication and authorization flows and allows you to indicate which grant types are appropriate based on the `grant_types` property of your Auth0-registered Application.
+
+For example, let's say you are securing a mobile app. In this case, you'd use the [Authorization Code using Proof Key for Code Exchange (PKCE) Grant](/flows/concepts/auth-code-pkce).
+
+Alternatively, if you were securing a client-side app (such as a single-page app), you'd use the [Implicit Grant](/flows/concepts/implicit).
+
+::: note
+Not sure which grant type is appropriate for your use case? Refer to [Which OAuth 2.0 flow should I use?](/api-auth/which-oauth-flow-to-use) for help.
+:::
+
+## Keep Reading
+
+* [Available Grant Types](/applications/reference/grant-types-available)
+* [Auth0 Grant Types Mapping](/applications/reference/grant-types-auth0-mapping)
+* [Update Grant Types Using the Dashboard](/dashboard/guides/applications/update-grant-types)
+* [Update Grant Types Using the Management API](/api/management/guides/applications/update-grant-types)
+* [Legacy Grant Types](/applications/concepts/grant-types-legacy)
diff --git a/articles/applications/concepts/client-secret.md b/articles/applications/concepts/client-secret.md
new file mode 100644
index 0000000000..3c97f7efa3
--- /dev/null
+++ b/articles/applications/concepts/client-secret.md
@@ -0,0 +1,17 @@
+---
+title: Client Secret
+description: Learn about client secrets.
+topics:
+ - applications
+ - client-secrets
+contentType:
+ - concept
+useCase:
+ - build-an-app
+---
+
+# Client Secret
+
+A client secret is a secret known only to your application and the authorization server. It protects your resources by only granting [tokens](/tokens) to authorized requestors.
+
+Protect your client secrets and never include them in mobile or browser-based apps. If your client secret is ever compromised, you should [rotate to a new one](/dashboard/guides/applications/rotate-client-secret) and update all authorized apps with the new client secret.
\ No newline at end of file
diff --git a/articles/applications/concepts/grant-types-legacy.md b/articles/applications/concepts/grant-types-legacy.md
new file mode 100644
index 0000000000..795ad11152
--- /dev/null
+++ b/articles/applications/concepts/grant-types-legacy.md
@@ -0,0 +1,36 @@
+---
+title: Legacy Grant Types
+description: Learn about legacy grant types and more secure alternatives.
+topics:
+ - applications
+ - client-secrets
+contentType: concept
+useCase:
+ - build-an-app
+---
+
+# Legacy Grant Types
+
+Legacy grant types are traditional grant types supported for legacy customers only. If you are a legacy customer, we highly recommend moving to a more secure alternative.
+
+::: warning
+As of 8 June 2017, all Auth0 Applications were given a `grant_types` property that **must** be populated. To avoid changes in functionality for Auth0 customers at that time, we populated the `grant_types` property for all existing Applications with **all** Auth0 legacy, Auth0 extension, and specification-conforming grant types.
+
+At this time, new Auth0 customers were no longer able to add legacy grant types to their applications. Legacy grant types are only available for previous customers while they migrate to new flows, to avoid breaking changes. If you were a customer prior to 8 June 2017, you can [use the Dashboard](/dashboard/guides/applications/update-grant-types) or [use the Management API](/api/management/guides/applications/update-grant-types) to enable a legacy grant type.
+:::
+
+## Secure Alternatives
+
+If you're currently using a legacy grant type, refer to the chart below to see which of the secure alternatives you should use instead.
+
+| Legacy Grant Type | Alternative |
+|:-----|:----|
+|`http://auth0.com/oauth/legacy/grant-type/ro` | Use the [/oauth/token](/api/authentication#authorization-code) endpoint with a grant type of `password`. See [Resource Owner Password Credentials Exchange](/api-auth/tutorials/adoption/password) and [Executing the Resource Owner Password Grant](/api-auth/tutorials/password-grant) for additional information. |
+| `http://auth0.com/oauth/legacy/grant-type/ro/jwt-bearer` | This feature is disabled by default. If you would like this feature enabled, please [contact support](https://support.auth0.com/) to discuss your use case and prevent the possibility of introducing security vulnerabilities. |
+| `http://auth0.com/oauth/legacy/grant-type/delegation/refresh_token` | Use the `oauth/token` endpoint to obtain Refresh Tokens. See [OIDC-conformant Refresh Tokens](/api-auth/tutorials/adoption/refresh-tokens) for more info. |
+| `http://auth0.com/oauth/legacy/grant-type/delegation/id_token` | This feature is disabled by default. If you would like this feature enabled, please [contact support](https://support.auth0.com/) to discuss your use case and prevent the possibility of introducing security vulnerabilities. |
+| `http://auth0.com/oauth/legacy/grant-type/access_token` | Use browser-based social authentication. |
+
+::: note
+Those implementing Passwordless Authentication should use [Universal Login](/universal-login) instead of the `oauth/ro` endpoint.
+:::
diff --git a/articles/applications/connections.md b/articles/applications/connections.md
deleted file mode 100644
index abf585d450..0000000000
--- a/articles/applications/connections.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-description: Explains what Connections are and how they are associated with Auth0 Applications.
-crews: crew-2
----
-# Application Connections
-
-Connections are sources of users. They are categorized into Database, Social, Enterprise and Passwordless and can be shared among different applications.
-
-You can configure any number of connections for your applications to use in your Dashboard. To view all the connections that you have configured or create new ones navigate to [Dashboard](${manage_url}/#/) and select the connection type you want:
-- [Database](${manage_url}/#/connections/database)
-- [Social](${manage_url}/#/connections/social)
-- [Enterprise](${manage_url}/#/connections/enterprise)
-- [Passwordless](${manage_url}/#/connections/passwordless)
-
-For more details on the connections you can configure refer to: [Identity Providers Supported by Auth0](/identityproviders).
-
-## Example multi-tenant configuration
-
-If you have two separate domains (for example, public facing and internal), or two groups of connections you'd like to allow users, the best solution is to create a second Auth0 tenant via the settings menu in the top right on the [Dashboard](${manage_url}). This will allow you to have separate sets of users, applications, and connections for the two groups of users and applications you need to support.
-
-Let's suppose that you have two applications: an internal timesheets application and a customer portal. Users should login to the timesheets application either using their Active Directory credentials or their Google apps social connection. The customer portal on the other hand should be accessible via Facebook, Google, or LinkedIn authentication.
-
-You can configure this in Auth0 as follows:
-
-- Create a tenant `Fabrikam-Internal` for your internal domain, and an application within it `Fabrikam Employee Timesheets` for timesheets.
-- Create a second tenant `Fabrikam-Public` for your public-facing domain, and an application within it `Fabrikam Customer Portal` for the customer portal.
-- Configure the following [Enterprise connections](${manage_url}/#/connections/enterprise) for the `Fabrikam-Internal` tenant: Active Directory / LDAP, and Google Apps; once each is set up, check the **Applications** tab to enable them.
-- Configure the following [Enterprise connection](${manage_url}/#/connections/enterprise) for the `Fabrikam-Public` tenant: Google Apps; once it is set up, check the **Applications** tab to enable it.
-- Configure the following [Social connections](${manage_url}/#/connections/social) for the `Fabrikam-Public` tenant: Facebook, LinkedIn; once each is set up, check the **Applications** tab to enable it.
diff --git a/articles/applications/enable-android-app-links.md b/articles/applications/enable-android-app-links.md
deleted file mode 100644
index a809581a30..0000000000
--- a/articles/applications/enable-android-app-links.md
+++ /dev/null
@@ -1,61 +0,0 @@
----
-description: How to enable Android App Links support for your Auth0 application
----
-
-# Enable Android App Links Support for your Auth0 Application
-
-The following document outlines how to configure [Android App Links](https://developer.android.com/training/app-links/index.html) for your Auth0 application.
-
-Android App Links allow an application to designate itself as the default handler of a given type of link. For example, clicking a URL in an email would open the link in the designated application.
-
-## Provide Your App's Package Name and Certificate Fingerprint
-
-You can establish the app link with Auth0 using [Applications](${manage_url}/#/applications) page of the [Auth0 Dashboard](${manage_url}).
-
-Select the Application you want to link with your Android application. You will see the **Settings** page for the Application.
-
-
-
-Scroll to the bottom of the **Settings** page and click **Show Advanced Settings.**
-
-
-
-Select the **Mobile Settings** tab, then provide the [App Package Name](https://developer.android.com/studio/build/application-id.html) and the SHA256 fingerprints of your app’s signing certificate for your Android application.
-
-You can generate the fingerprint using the Java keytool in your terminal:
-
-```bash
-keytool -list -v -keystore my-release-key.keystore
-```
-
-::: note
-For more information on signing certificates, check out the [Sign Your App](https://developer.android.com/studio/publish/app-signing.html) page of the Android developer documentation.
-:::
-
-
-
-Click **Save Changes** when done.
-
-## Test Your App Link
-
-You can test your app link by navigating to the following URL using your browser:
-
-`https://${account.namespace}/.well-known/assetlinks.json`
-
-If the link is successful, you will return the following JSON (formatted for readability):
-
-```json
-[{
- "relation": ["delegate_permission/common.handle_all_urls"],
- "target": {
- "namespace": "android_app",
- "package_name": "com.mycompany.app1",
- "sha256_cert_fingerprints":
- ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
- }
-}]
-```
-
-::: note
-See [Verify Android App Links](https://developer.android.com/training/app-links/verify-site-associations.html#testing) for further information on testing your app link.
-:::
diff --git a/articles/applications/enable-universal-links.md b/articles/applications/enable-universal-links.md
deleted file mode 100644
index 7e80253de4..0000000000
--- a/articles/applications/enable-universal-links.md
+++ /dev/null
@@ -1,58 +0,0 @@
----
-description: How to enable Universal Links support for your Auth0 app in Xcode
----
-
-# Enable Universal Links Support for your Auth0 Application in Xcode
-
-Because universal links establish a *verified relationship between domains and applications*, both your Auth0 Application settings and your iOS application need to be in sync. To do this, you need to provide Auth0 with the following information:
-
-* `Team ID`;
-* `Bundle identifier`.
-
-## Find Your Apple `Team ID` and `Bundle Identifier`
-
-To find your Apple `Team ID`, go to your [Apple developer account summary page](https://developer.apple.com/membercenter/index.action#accountSummary).
-
-To find your iOS application's `Bundle identifier`, go to its [Xcode project settings](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/ConfiguringYourApp/ConfiguringYourApp.html) page:
-
-
-
-## Provide Your Apple `Team ID` and `Bundle Identifier` to Auth0
-
-You can establish the universal link from the Auth0 side using [Applications](${manage_url}/#/clients) page of the [Management Dashboard](${manage_url}).
-
-Select the Application you want to link with your iOS application. You will see the *Settings* page for the Application.
-
-
-
-Scroll to the bottom of the *Settings* page and click *Show Advanced Settings.*
-
-
-
-Select the *Mobile Settings* tab and provide the **Team ID** and the **App bundler identifier** values for your iOS application.
-
-
-
-Click **Save Changes** when done.
-
-## Test Your Universal Link
-
-To test this, check whether the universal links apple app site association file is available for your application. Go to your browser and open: https://YOURACCOUNT.auth0.com/apple-app-site-association (replace YOURACCOUNT with your Auth0 account name).
-
-You can test your universal link by navigating to the following URL using your browser:
-
-`${account.namespace}/apple-app-site-association`
-
-If the link is successful, you will return the following JSON (formatted for readability):
-
-```json
-{
- "applinks": {
- "apps": [],
- "details": [{
- "appID": "86WQXF56BC.com.auth0.Passwordless-Email",
- "paths": ["/ios/com.auth0.Passwordless-Email/*"]
- }]
- }
-}
-```
diff --git a/articles/applications/guides/enable-third-party-apps.md b/articles/applications/guides/enable-third-party-apps.md
new file mode 100644
index 0000000000..bcd3c1712c
--- /dev/null
+++ b/articles/applications/guides/enable-third-party-apps.md
@@ -0,0 +1,91 @@
+---
+title: Enable Third-Party Applications
+description: Learn how to enable third-party applications for your tenant.
+topics:
+ - applications
+ - application-types
+ - third-party-applications
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# Enable Third-Party Applications
+
+You can enable third-party applications for your tenant. See [First-Party and Third-Party Applications](/applications/concepts/app-types-first-third-party) for details on the differences between the two types of applications.
+
+1. [Update your application's ownership to third-party](/api/management/guides/applications/update-ownership) in Auth0.
+
+ By default, applications registered in Auth0 are first-party applications. If you want your application to be a third-party application, you must update its ownership.
+
+2. [Promote the connections you will use with third-party applications to domain level](/api/management/guides/connections/promote-connection-domain-level) in Auth0.
+
+ Third-party applications can only authenticate users from [connections](/connections) flagged as domain-level connections. Domain-level connections can be enabled for selected first-party applications while also being open to all third-party application users for authentication.
+
+3. Update your application's login page. If you use [Lock](/libraries/lock/v11) in the [Universal Login Page](/universal-login/classic), you must also:
+
+ - Upgrade to Lock version 11 or later
+ - Set the `__useTenantInfo: config.isThirdPartyClient` flag when instantiating Lock
+ - *For [Private Cloud](/private-cloud) users only*: Set the [`configurationBaseUrl` option](https://auth0.com/docs/libraries/lock/v11/configuration#configurationbaseurl-string-) to `https://{config.auth0Domain}/` when instantiating Lock
+
+## Access Token `current_user_*` scopes
+
+Neither first- nor third-party applications can use [ID Tokens](/tokens/concepts/id-tokens) to invoke [Management API](/api/management/v2) endpoints. Instead, they should get [Access Tokens](/api/management/v2/tokens) with the following `current_user_*` scopes required by each endpoint:
+
+| Scope | Endpoint |
+| - | - |
+| `read:current_user` | [List or search users](/api/management/v2#!/Users/get_users) |
+| | [Get a user](/api/management/v2#!/Users/get_users_by_id) |
+| | [Get user MFA enrollments](/api/management/v2#!/Users/get_enrollments) |
+| `update:current_user_metadata` | [Update a user](/api/management/v2#!/Users/patch_users_by_id) |
+| | [Delete a user's multi-factor provider](/api/management/v2#!/Users/delete_multifactor_by_provider) |
+| `create:current_user_device_credentials` | [Create a device public key](/api/management/v2#!/Device_Credentials/post_device_credentials) |
+| `delete:current_user_device_credentials` | [Delete a device credential](/api/management/v2#!/Device_Credentials/delete_device_credentials_by_id) |
+| `update:current_user_identities` | [Link a user account](/api/management/v2#!/Users/post_identities) |
+| | [Unlink a user identity](/api/management/v2#!/Users/delete_user_identity_by_user_id) |
+
+## Sample script
+
+```html
+
+...
+
+```
+
+## Keep reading
+* [View Application Ownership](/api/management/guides/applications/view-ownership)
+* [Applications](/applications)
+* [Confidential and Public Applications](/applications/concepts/app-types-confidential-public)
+* [Auth0 Grant Types Mapping](/applications/reference/grant-types-auth0-mapping)
+* [User consent and third-party applications](/api-auth/user-consent)
diff --git a/articles/applications/how-to-rotate-client-secret.md b/articles/applications/how-to-rotate-client-secret.md
deleted file mode 100644
index 608a3ba224..0000000000
--- a/articles/applications/how-to-rotate-client-secret.md
+++ /dev/null
@@ -1,56 +0,0 @@
----
-description: This page lists different ways of how to update your application's secret.
-crews: crew-2
----
-
-# Rotate the Client Secret
-
-The client secret protects your resources by only granting tokens to requestors if they're authorized. Protect your client secrets; if any are ever compromised, you should rotate to a new one. Please remember that all authorized apps will therefore need to be updated with the new client secret.
-
-## Rotate the Client Secret in the Dashboard
-
-You can rotate your client secret under [Applications in the Dashboard](${manage_url}/#/applications). Choose the application you wish to edit by clicking on its name *or* the **Settings** gear icon associated with the application.
-
-
-
-On the **Settings** page, the **Client Secret** will be the fourth parameter listed. To the right, click on the **rotation** icon to rotate your secret. You can view you your new secret by checking the box next to **Reveal client secret**.
-
-Scroll to the bottom of the Settings page, and click **Save Changes**.
-
-
-
-## Rotate the Client Secret Using the Management API
-
-You can rotate your application's secret by making a `POST` call to the [Rotate a Client Secret endpoint](/api/management/v2#!/Clients/post_rotate_secret) of the Management API.
-
-Be sure to replace `YOUR_CLIENT_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your client ID and Access Token, respectively.
-
-::: note
-To make calls to the Management API, you must [get and use a valid Access Token](/api/management/v2/tokens).
-:::
-
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/api/v2/clients/YOUR_CLIENT_ID/rotate-secret",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [{
- "name": "Authorization",
- "value": "Bearer MGMT_API_ACCESS_TOKEN"
- }],
- "queryString": [],
- "postData": {},
- "headersSize": -1,
- "bodySize": -1,
- "comment": ""
-}
-```
-
-## Update Authorized Applications
-
-Once you've rotated your client secret, you must update any authorized applications with the new value.
-
-To make sure that you see as little downtime as possible when connecting your apps to your Auth0 application, we suggest you store the new client secret as a fallback to the previous secret. Then, if the connection doesn't work with the old secret, your app will use the new secret.
-
-Secrets can be stored in a list (or similar structure) to track keys until they're no longer needed. Once you're sure that an old secret is obsolete, you can remove its value from your app.
diff --git a/articles/applications/index.md b/articles/applications/index.md
index 91e1e36547..2f3bf9a89a 100644
--- a/articles/applications/index.md
+++ b/articles/applications/index.md
@@ -1,91 +1,52 @@
---
-description: Explains the basics of creating and using Auth0 Applications.
-toc: true
+description: Understand the basics of creating and using Auth0 Applications.
+topics:
+ - applications
+contentType:
+ - concept
+useCase:
+ - build-an-app
---
-# Applications
+# Applications in Auth0
-An Auth0 **application** represents your application and allows use of Auth0 for authentication. The term application does not imply any particular implementation characteristics. Your application can be a native app that executes on a mobile device, a single page app that executes on a browser, or a regular web app that executes on a server.
+The term *application* or *app* in Auth0 does not imply any particular implementation characteristics. For example, it could be a native app that executes on a mobile device, a single-page app that executes on a browser, or a regular web app that executes on a server.
-## Application Types
+Auth0 categorizes apps based on these characteristics:
-::: note
-Auth0 differentiates between [public and private applications](/applications/application-types#confidential-vs-public-applications), as well as [first- vs. third-party applications](/applications/application-types#first-vs-third-party-applications).
-:::
-
-There are four application types in Auth0. Depending on which type you choose, you'll see [different settings you can configure](/applications/application-settings).
-
-- **Native**: Used for mobile, desktop or hybrid apps, than run natively in a device, like Android, Ionic or iOS. For a complete listing of the SDKs Auth0 offers for mobile apps refer to: [Native SDKs](/quickstart/native).
-
-- **Single Page Web Applications**: Used for JavaScript front-end apps that run on a browser, like Angular, jQuery or React. For a complete listing of the SDKs Auth0 offers for SPAs refer to: [Single Page App SDKs](/quickstart/spa).
-
-- **Regular Web Applications**: Used for traditional web applications that run on a server, like ASP .NET, Java or Node.js. For a complete listing of the SDKs Auth0 offers for Web Apps refer to: [Web App SDKs](/quickstart/webapp).
-
-- **Machine to Machine Applications**: Used for server to server applications like CLIs, daemons or services running on your backend. Typically you would use this option if you have a service that requires access to an API.
-
-## How to configure an Application
-
-Navigate to the [dashboard](${manage_url}) and click on the [Applications](${manage_url}/#/applications) menu option on the left. By default, you should have one application named *Default App*. You can either configure this one or create a new one by clicking the **+ Create Application** button.
-
-The *Create Application* windows pops open. Set a descriptive name for your application and select the application type. The application type should match your application.
-
-
-
-After you set the name and application type, click **Create**.
+* **What type of app is it?**: To add authentication to your app, you must register it in the Auth0 Dashboard and select from one of the following app types:
+ - [Regular web app](/dashboard/guides/applications/register-app-regular-web): Traditional web apps that perform most of their application logic on the server (such as Express.js or ASP.NET).
+ - [Single-page app (SPA)](/dashboard/guides/applications/register-app-spa): JavaScript apps that perform most of their user interface logic in a web browser, communicating with a web server primarily using APIs (such as AngularJS + Node.js or React).
+ - [Native app](/dashboard/guides/applications/register-app-native): Mobile or Desktop apps that run natively in a device (such as iOS or Android).
+ - [Machine-to-machine (M2M) app](/dashboard/guides/applications/register-app-m2m): Non-interactive apps, such as command-line tools, daemons, IoT devices, or services running on your back-end. Typically, you use this option if you have a service that requires access to an API.
-A new application will be created and you will be redirected to this application's view that has four tabs:
+* **Can the app securely hold credentials?**: According to the [OAuth 2.0 spec](https://tools.ietf.org/html/rfc6749#section-2.1), apps can be classified as either *public* or *confidential*; confidential apps can hold credentials securely, while public apps cannot. See [Confidential and Public Applications](/applications/concepts/app-types-confidential-public) for details.
-- [Quick Start](${manage_url}/#/applications/${account.clientId}/quickstart): Lists all available Quick Starts, filtered by your application's type.
+* **Who owns the app?**: Whether an app is classified as first- or third-party depends on the app ownership and control. First-party apps are controlled by the same organization or person that owns the Auth0 domain. Third-party apps enable external parties or partners to securely access protected resources behind your API. See [First-Party and Third-Party Applications](/applications/concepts/app-types-first-third-party) for details.
-- [Settings](${manage_url}/#/applications/${account.clientId}/settings): Lists all the available settings for your application.
+## Manage app settings
- ::: note
- Please see [Application Settings](/applications/application-settings) for detailed information.
- :::
+You register apps on the [Dashboard > Applications > Settings](${manage_url}/#/applications/${account.clientId}/settings) page. See [Application Settings](/dashboard/reference/settings-application) for details.
-- [Addons](${manage_url}/#/applications/${account.clientId}/addons): Add-ons are extensions associated with applications. They are typically third-party APIs used by the application(s) for which Auth0 generates Access Tokens. For more details refer to: [Addons](/applications/addons).
+In addition to setting up apps in the Dashboard, you can also set up apps programmatically as described in the [OpenID Connect (OIDC) Dynamic Client Registration 1.0 ](https://openid.net/specs/openid-connect-registration-1_0.html) specification. See [Dynamic Client Registration](/api-auth/dynamic-client-registration) for details.
-- [Connections](${manage_url}/#/applications/${account.clientId}/connections): Connections are sources of users. They are categorized into Database, Social and Enterprise and can be shared among different applications. For more details refer to: [Connections](/applications/connections). For a detailed list on the supported Identity Providers refer to: [Identity Providers Supported by Auth0](/identityproviders).
-
-::: note
-After creating your first application, set the environment for your tenant to: development, staging, or production. For more information refer to [Set Up Multiple Environments](/dev-lifecycle/setting-up-env#set-the-environment).
-:::
-
-## How to Delete an Application
-
-Navigate to the [Application Settings](${manage_url}/#/applications/${account.clientId}/settings) and scroll to the end of the page. Under the *Danger Zone* section you can find the **Delete Application** button. This operation cannot be undone.
-
-Once you click on the button a pop-up window will ask you to confirm the action. Click **Yes, delete application** to permanently remove the application.
-
-::: note
-You can also delete an application using the [DELETE /api/v2/clients/{id} endpoint](/api/management/v2#!/Clients/delete_clients_by_id) of the Management API.
+::: panel Multi-Tenancy
+You can set up up a more complex configuration that allows users to log in differently for different apps. See [Using Auth0 to Secure Your Multi-Tenant Applications](/design/using-auth0-with-multi-tenant-apps) and [Create Multiple Tenants](/dashboard/guides/tenants/create-multiple-tenants).
:::
-## Application Auditing
-
-Auth0 stores log data of both actions taken in the dashboard by the administrators, as well as authentications made by your users. The logs include many of the actions performed by the user like failing to login to an application or requesting a password change. For more details refer to: [Logs](/logs).
-
-If you use a third-party application for log management, like Sumo Logic, Splunk or Loggly, you can use Auth0 Extensions to export your logs there. For details on the available extensions and how to configure them refer to: [Extensions](/extensions).
-
-## Dynamic Client Registration
-
-You can use the Auth0 to programmatically create applications, as described in the [OIDC Dynamic Client Registration 1.0 specification](https://openid.net/specs/openid-connect-registration-1_0.html). For more details please refer to [Dynamic Client Registration](/api-auth/dynamic-client-registration).
-
-## Next Steps
+By default, Auth0 enables all connections associated with your tenant when you create a new application. To change this, [update application connections](/dashboard/guides/applications/update-app-connections) in the Application Settings in the Dashboard.
-Once you have configured your Application, some common next steps to take are:
+## Monitor apps
-- **Configure a Connection** and enable it for your Application. For details refer to [Application Connections](/applications/connections). For a list of the supported Identity Providers refer to [Identity Providers Supported by Auth0](/identityproviders).
+You can [monitor apps](/monitoring/guides/monitor-applications) and perform end-to-end testing using your own tests. Auth0 stores [log data](/logs) including Dashboard administrator actions, successful and failed user authentications, and password change requests. You can use Auth0 [Extensions](/extensions) to export your log data and use tools like Sumo Logic, Splunk, or Loggly to analyze and store your log data.
-- **Configure your app** to use your Auth0 Application. For detailed instructions and samples for a variety of technologies, refer to our [quickstarts](/quickstarts). There you can find information on how to implement login and logout (using [Lock](/libraries/lock) or [Auth0.js](/libraries/auth0js)), handle your user sessions, retrieve and display user profile information, add [Rules](/rules) to customize your flow, and more.
+## Remove apps
- ::: note
- For background theory on application authentication flows, refer to [Application Authentication](/application-auth).
- :::
+You can [remove an application using the Auth0 Dashboard](/dashboard/guides/applications/remove-app) or the [Management API](/api/management/guides/applications/remove-app).
-- Use our latest [API Authorization](/api-auth) features to **call an API**.
+## Manage client secrets
-- **Use [our APIs](/api/info)**.
+You can [rotate an app's Client Secret](/dashboard/guides/applications/rotate-client-secret) using the Auth0 Dashboard or the [Management API](/api/management/guides/applications/rotate-client-secret).
- - The [Authentication API](/api/authentication) handles all the primary identity related functions (login, logout, get user profile, and so forth). Most users consume this API through our [Quickstarts](/quickstarts), the [Auth0.js library](/libraries/auth0js) or the [Lock widget](/libraries/lock). However, if you are building all of your authentication UI manually you will have to interact with this API directly.
+## Grant types
- - The [Management API](/api/management/v2) can be used to automate various tasks in Auth0 such as creating users.
+Auth0 provides many different authentication and authorization grant types or *flows* and allows you to indicate which grant types are appropriate based on the `grant_types` property of your Auth0-registered app. See [Application Grant Types](/applications/concepts/application-grant-types) for more details.
diff --git a/articles/applications/reference/grant-types-auth0-mapping.md b/articles/applications/reference/grant-types-auth0-mapping.md
new file mode 100644
index 0000000000..d0808c59d3
--- /dev/null
+++ b/articles/applications/reference/grant-types-auth0-mapping.md
@@ -0,0 +1,61 @@
+---
+title: Auth0 Grant Types Mapping
+description: Learn which grant types are available to which application types with Auth0.
+toc: true
+topics:
+ - applications
+ - application-types
+ - grant-types
+contentType: reference
+useCase:
+ - build-an-app
+---
+
+# Auth0 Grant Types Mapping
+
+When registered, Auth0 Applications have access to different grant types based on [application](/applications) type. The biggest deciding factor is whether the application is [confidential or public](/applications/concepts/app-types-confidential-public).
+
+Additionally, trusted first-party applications have access to additional grant types.
+
+## Public applications
+
+When a **Native App** or **Single-Page App** is registered in the Dashboard, it is automatically flagged as a public application, which is indicated by a `token_endpoint_auth_method` flag set to `none`.
+
+By default, Auth0 creates public applications with the following `grant_types` enabled:
+
+* `implicit`
+* `authorization_code`
+* `refresh_token`
+
+**Native Apps** can also use the `device_code` grant type.
+
+::: note
+Public applications **cannot** use the `client_credentials` grant type. To use this grant type, you must indicate that the application is confidential rather than public. Use the [Management API](/api/management/v2#!/Clients/patch_clients_by_id) to set the **token_endpoint_auth_method** to `client_secret_post` or `client_secret_basic`.
+:::
+
+## Confidential applications
+
+When a **Regular Web App** or **Machine-to-Machine (M2M) App** is registered in the Dashboard, it is automatically flagged as a confidential application, which is indicated by a `token_endpoint_auth_method` flag set to anything *except* `none`.
+
+By default, Auth0 creates confidential applications with the following `grant_types` enabled:
+
+* `implicit`
+* `authorization_code`
+* `refresh_token`
+* `client_credentials`
+
+## Trusted first-party applications
+
+Trusted first-party applications have the same `grant_types` enabled as confidential applications, plus the following:
+
+* `password`
+* `http://auth0.com/oauth/grant-type/password-realm`
+* `http://auth0.com/oauth/grant-type/mfa-oob`
+* `http://auth0.com/oauth/grant-type/mfa-otp`
+* `http://auth0.com/oauth/grant-type/mfa-recovery-code`
+
+::: note
+If you are using the [Dashboard](${manage_url}) to enable or disable these grant types, be aware that all the Password and MFA grant types are enabled when you add the `Password` or `MFA` grant type to your Application. You cannot select them individually.
+:::
+
+For more info about first-party and third-party applications, see [First-Party and Third-Party Applications](/applications/concepts/app-types-first-third-party).
diff --git a/articles/applications/reference/grant-types-available.md b/articles/applications/reference/grant-types-available.md
new file mode 100644
index 0000000000..f4f2946b74
--- /dev/null
+++ b/articles/applications/reference/grant-types-available.md
@@ -0,0 +1,55 @@
+---
+title: Available Grant Types
+description: Learn which grant types are available with Auth0.
+toc: true
+topics:
+ - applications
+ - grant-types
+contentType: reference
+useCase:
+ - build-an-app
+---
+# Available Grant Types
+
+Various grant types are valid when registering Auth0 Applications. These can be divided into the following categories:
+
+* **[Spec-conforming grants](#spec-conforming-grants)**: Grants defined by and conforming to external specifications (such as OpenID Connect (OIDC)).
+* **[Auth0 extension grants](#auth0-extension-grants)**: Auth0-specific grants that conform to the [OAuth extension mechanism](https://tools.ietf.org/html/rfc6749#section-4.5) to support additional clients or to provide a bridge between OAuth and other trust frameworks.
+* **[Auth0 legacy grants](#auth0-legacy-grants)**: Traditional grant types supported for legacy customers only. If you are a legacy customer, we highly recommend moving to a more secure alternative. For info on working with legacy grant types and their alternatives, see [Legacy Grant Types](/applications/concepts/grant-types-legacy).
+
+## Spec-conforming grants
+
+| `grant_type` | More info |
+|:-----|:----|
+| `implicit` | [Implicit Grant](/flows/concepts/implicit) |
+| `authorization_code` | [Authorization Code Grant](/flows/concepts/auth-code) |
+| `client_credentials` | [Client Credentials Grant](/flows/concepts/client-credentials) |
+| `password` | [Resource Owner Password Grant](/api-auth/grant/password) |
+| `refresh_token` | [Use Refresh Tokens](/tokens/guides/use-refresh-tokens) |
+| `urn:ietf:params:oauth:grant-type:device_code` | [Device Authorization Grant](/flows/concepts/device-auth) |
+
+## Auth0 extension grants
+
+| `grant_type` | More info |
+|:-----|:----|
+| `http://auth0.com/oauth/grant-type/password-realm` | [Use an extension grant similar to the Resource Owner Password Grant that includes the ability to indicate a specific realm](/api-auth/grant/password#realm-support) |
+| `http://auth0.com/oauth/grant-type/mfa-oob` | [Multi-factor Authentication OOB Grant Request](/mfa/guides/mfa-api/multifactor-resource-owner-password#mfa-oob-grant-request) |
+| `http://auth0.com/oauth/grant-type/mfa-otp` | [Multi-factor Authentication OTP Grant Request](/mfa/guides/mfa-api/multifactor-resource-owner-password#mfa-otp-grant-request) |
+| `http://auth0.com/oauth/grant-type/mfa-recovery-code` | [Multi-factor Authentication Recovery Grant Request](/mfa/guides/mfa-api/multifactor-resource-owner-password#mfa-recovery-grant-request) |
+| `http://auth0.com/oauth/grant-type/passwordless/otp` | [Embedded Passwordless Login Grant Request](/connections/passwordless#implementing-login) |
+
+## Auth0 legacy grants
+
+Legacy grants include:
+
+* `http://auth0.com/oauth/legacy/grant-type/ro`
+* `http://auth0.com/oauth/legacy/grant-type/ro/jwt-bearer`
+* `http://auth0.com/oauth/legacy/grant-type/delegation/refresh_token`
+* `http://auth0.com/oauth/legacy/grant-type/delegation/id_token`
+* `http://auth0.com/oauth/legacy/grant-type/access_token`
+
+For info on working with legacy grant types and their alternatives, see [Legacy Grant Types](/applications/concepts/grant-types-legacy).
+
+## Keep reading
+
+* To learn which grant types are enabled for different application types, see [Auth0 Grant Types Mapping](/applications/reference/grant-types-auth0-mapping).
diff --git a/articles/applications/reference/wildcard-subdomains.md b/articles/applications/reference/wildcard-subdomains.md
new file mode 100644
index 0000000000..74f968b6d1
--- /dev/null
+++ b/articles/applications/reference/wildcard-subdomains.md
@@ -0,0 +1,35 @@
+---
+title: Wildcards for Subdomains
+description: Describes wildcards for subdomains function in application configuration.
+toc: true
+topics:
+ - applications
+contentType: reference
+useCase:
+ - build-an-app
+---
+# Wildcards for Subdomains
+
+You can use wildcards for subdomain URL registration in your application configuration in the Dashboard with these fields:
+
+* **Allowed Callback URLs**: Set of URLs to which Auth0 is allowed to redirect users after they authenticate.
+* **Allowed Logout URLs**: List of URLs to which you can redirect users after they log out from Auth0.
+* **Allowed Origins (CORS)**: Set of URLs that will be allowed to make requests from JavaScript to Auth0 API (typically used with CORS).
+
+::: warning
+Avoid using wildcards for subdomains in application callbacks and allowed origins as it can make your application vulnerable to attacks. See [Application Settings Best Practices](/best-practices/application-settings) for this and other recommended settings.
+:::
+
+You can use the star symbol (`*`) as a wildcard for subdomains, but it must be used in accordance with the following rules in order to properly function:
+
+* The protocol of the URL **must** be `http:` or `https:`. `com.example.app://*.example.com` will not work.
+
+* The wildcard **must** be located in a subdomain within the hostname component. `https://*.com` will not work.
+
+* The wildcard **must** be located in the subdomain furthest from the root domain. `https://sub.*.example.com` will not work.
+
+* The URL **must not** contain more than one wildcard. `https://*.*.example.com` will not work.
+
+* A wildcard **may** be prefixed and/or suffixed with additional valid hostname characters. `https://prefix-*-suffix.example.com` will work.
+
+* A URL with a valid wildcard **will not** match a URL more than one subdomain level in place of the wildcard. `https://*.example.com` will not work with `https://sub1.sub2.example.com`.
diff --git a/articles/architecture-scenarios/_includes/_api-authentication-and-authorization.md b/articles/architecture-scenarios/_includes/_api-authentication-and-authorization.md
index ae0e6718bb..7c95f9b91b 100644
--- a/articles/architecture-scenarios/_includes/_api-authentication-and-authorization.md
+++ b/articles/architecture-scenarios/_includes/_api-authentication-and-authorization.md
@@ -9,9 +9,9 @@ An Access Token is obtained by authenticating the user with an Authorization Ser
::: panel What is an Access Token?
An Access Token (also referred to as `access_token`) is an opaque string representing an authorization issued to the application. It may denote an identifier used to retrieve the authorization information or may self-contain the authorization information (for example, the user's identity, permissions, and so forth) in a verifiable manner.
-It is quite common for Access Tokens to be implemented as [JSON Web Tokens](/jwt).
+It is quite common for Access Tokens to be implemented as [JSON Web Tokens](/tokens/concepts/jwts).
-For more information on Auth0 Access Tokens refer to [Access Token](/tokens/access-token).
+For more information on Auth0 Access Tokens refer to [Access Token](/tokens/concepts/access-tokens).
:::
An API can enforce fine-grained control over who can access the various endpoints exposed by the API. These permissions are expressed as scopes.
@@ -30,7 +30,7 @@ When a client asks the API to create a new timesheet entry, then the Access Toke
For more information on scopes refer to [Scopes](/scopes).
:::
-By using the OAuth 2.0 authorization framework, you can give your own applications or third-party applications limited access to your APIs on behalf of the application itself. Using Auth0, you can easily support different flows in your own APIs without worrying about the OAuth 2.0/OpenID Connect specification, or the many other technical aspects of API authorization.
+By using the OAuth 2.0 authorization framework, you can give your own applications or third-party applications limited access to your APIs on behalf of the application itself. Using Auth0, you can easily support different flows in your own APIs without worrying about the OAuth 2.0/OpenID Connect (OIDC) specification, or the many other technical aspects of API authorization.
::: panel OAuth Roles
In any OAuth 2.0 flow we can identify the following roles:
@@ -40,5 +40,5 @@ In any OAuth 2.0 flow we can identify the following roles:
- __Client__: an application requesting access to a protected resource on behalf of the Resource Owner.
- __Authorization Server__: the server that authenticates the Resource Owner, and issues Access Tokens after getting proper authorization. In this case, Auth0.
-Using [different grants types (or flows)](/api-auth/which-oauth-flow-to-use), these participants will interact to grant to the client apps limited access to the APIs you are building. As a result, the client app will obtain an `access_token` that can be used to call the API on behalf of the user.
+Using [different grants types (or flows)](/api-auth/which-oauth-flow-to-use), these participants will interact to grant to the client apps limited access to the APIs you are building. As a result, the client app will obtain an Access Token that can be used to call the API on behalf of the user.
:::
diff --git a/articles/architecture-scenarios/_includes/_api-configure-scopes.md b/articles/architecture-scenarios/_includes/_api-configure-scopes.md
index 571c464d01..148a374c9a 100644
--- a/articles/architecture-scenarios/_includes/_api-configure-scopes.md
+++ b/articles/architecture-scenarios/_includes/_api-configure-scopes.md
@@ -1,7 +1,7 @@
-### Configure the Scopes
+### Configure the Permissions
-Once the application has been created you will need to configure the Scopes which applications can request during authorization.
+Once the application has been created you will need to configure the Permissions which applications can request during authorization.
-In the settings for your API, go to the **Scopes** tab. In this section you can add all four of the scopes which were discussed before, namely `read:timesheets`, `create:timesheets`, `delete:timesheets`, `approve:timesheets`.
+In the settings for your API, go to the **Permissions** tab. In this section you can add all four of the scopes which were discussed before, namely `read:timesheets`, `create:timesheets`, `delete:timesheets`, `approve:timesheets`.
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/articles/architecture-scenarios/_includes/_api-implement.md b/articles/architecture-scenarios/_includes/_api-implement.md
index 70206c28f4..3a217a0af4 100644
--- a/articles/architecture-scenarios/_includes/_api-implement.md
+++ b/articles/architecture-scenarios/_includes/_api-implement.md
@@ -36,7 +36,7 @@ The validations that the API should perform are:
Part of the validation process is to also check the Client permissions (scopes), but we will address this separately in the next paragraph of this document.
-For more information on validating Access Tokens, refer to [Verify Access Tokens](/api-auth/tutorials/verify-access-token).
+For more information on validating Access Tokens, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
::: note
See the implementation in [Node.js](/architecture-scenarios/application/mobile-api/api-implementation-nodejs#2-secure-the-api-endpoints)
@@ -60,8 +60,8 @@ For retrieving the list of timesheets this is to ensure that we only return the
One of the standard JWT claims is the `sub` claim which identifies the principal that is the subject to the claim. In the case of the Implicit Grant flow this claim will contain the user's identity, which will be the unique identifier for the Auth0 user. You can use this to associate any information in external systems with a particular user.
-You can also use a custom claim to add another attribute of the user - such as their email address - to the `access_token` and use that to uniquely identify the user.
+You can also use a custom claim to add another attribute of the user - such as their email address - to the Access Token and use that to uniquely identify the user.
::: note
See the implementation in [Node.js](/architecture-scenarios/application/mobile-api/api-implementation-nodejs#4-determine-the-user-identity)
-:::
\ No newline at end of file
+:::
diff --git a/articles/architecture-scenarios/_includes/_api-signing-algorithms.md b/articles/architecture-scenarios/_includes/_api-signing-algorithms.md
index 9860ac274f..26c06a5eaf 100644
--- a/articles/architecture-scenarios/_includes/_api-signing-algorithms.md
+++ b/articles/architecture-scenarios/_includes/_api-signing-algorithms.md
@@ -3,7 +3,7 @@
When you create an API you have to select the algorithm your tokens will be signed with. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
::: note
-The signature is part of a JWT. If you are not familiar with the JWT structure please refer to: [JSON Web Tokens (JWTs) in Auth0](/jwt#what-is-the-json-web-token-structure-).
+The signature is part of a JWT. If you are not familiar with the JWT structure please refer to: [JSON Web Token Structure](/tokens/references/jwt-structure).
:::
To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. That algorithm, which is part of the JWT header, is the one you select for your API: `HS256` or `RS256`.
@@ -17,6 +17,3 @@ The most secure practice, and our recommendation, is to use __RS256__. Some of t
- Under HS256, If the private key is compromised you would have to re-deploy the API with the new secret. With RS256 you can request a token that is valid for multiple audiences.
- With RS256 you can implement key rotation without having to re-deploy the API with the new secret.
-::: note
-For a more detailed overview of the JWT signing algorithms refer to: [JSON Web Token (JWT) Signing Algorithms Overview](https://auth0.com/blog/json-web-token-signing-algorithms-overview/).
-:::
\ No newline at end of file
diff --git a/articles/architecture-scenarios/_includes/_architecture/_custom-domains.md b/articles/architecture-scenarios/_includes/_architecture/_custom-domains.md
new file mode 100644
index 0000000000..0f2d1ea2a4
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_architecture/_custom-domains.md
@@ -0,0 +1,16 @@
+When you setup your Auth0 tenant, the URL for accessing that tenant will be of the form `https://${account.tenant}.auth0.com`. Providing a [Custom Domain](/custom-domains) (also known as a vanity URL), for your Auth0 tenant is not only an important factor for supporting your Branding requirements, but more importantly will also provide you with security benefits too:
+
+* Some browsers will, by default, make it [difficult to communicate in an iFrame if you don't have a shared domain](/api-auth/token-renewal-in-safari).
+* A vanity URL makes phishing more difficult as the phisher must also create a vanity URL to mimic yours. For example, with a custom domain you can use your own certificate to get an "Extended Validation", making phishing even harder.
+
+::: note
+You are allowed only one custom domain per Auth0 Tenant. This is because a tenant in Auth0 is intended to represent a “domain” of users. If you need more than one vanity URL, then you likely have more than one domain of users and should be using multiple tenants.
+:::
+
+Your custom domain name should also give the user confidence that this is the appropriate place to enter their credentials, and we recommend that you create your custom domain in all environments early on to ensure that you are testing consistently between environments. **It's extremely important to train your users to to look for suspicious URLs when entering their credentials!**
+
+::: panel Best Practice
+Create a custom domain (a.k.a. `CNAME`) for your Auth0 tenant, and also create one in development too so you can ensure you have managed the `CNAME` correctly. For example, you could create a `CNAME` which maps `login.mycompany.com` to `mycompany-prod.auth0.com`.
+:::
+
+In almost all cases, customers have been most successful when adopting a strategy of a centralised domain for authentication across multiple product or service brands. This strategy provides users with a consistent UX, and also mitigates the complexity of deploying and maintaining multiple Auth0 tenants in a production environment. If you are considering having multiple domains for different brands, please refer to the [Branding](/architecture-scenarios/implementation/${platform}/${platform}-branding) guidance before you begin implementing.
diff --git a/articles/architecture-scenarios/_includes/_architecture/_introduction.md b/articles/architecture-scenarios/_includes/_architecture/_introduction.md
new file mode 100644
index 0000000000..ab22539da6
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_architecture/_introduction.md
@@ -0,0 +1,37 @@
+Understanding your application is key to understanding how Auth0 can be leveraged to meet your needs. From experience, our most successful customers start with a visualization of their proposed - or in many cases existing - architecture and use this as a basis for reference as they progress. Understanding where your application fits within your organization is also important; Auth0 [Accounts and Tenants](/getting-started/the-basics#account-and-tenants) form the basis for the grouping and structuring of Auth0 assets, and it may be that you’ll need to leverage an existing Auth0 deployment in order to integrate with [Single Sign-on (SSO)](/sso/current/introduction), centralized user [Profile Management](/architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt), consolidated billing, or the like.
+
+::: panel Best Practice
+If you do have multiple applications, and you need to leverage SSO, then we recommend you check out our [How to Implement Single Sign-On](https://auth0.com/learn/how-to-implement-single-sign-on/) training guidance before continuing.
+:::
+
+The value of investing time on the landscape of the architecture up-front is something that we have found pays dividends in the long run, and there are a number of things you will want to consider when looking at functionality and workflow:
+
+* What should the URL look like when Auth0 needs to present a web page to a user?
+* How can Auth0 be structured to support your SDLC (Software Development Lifecycle)?
+* How can you ensure that your Auth0 tenants are appropriately associated with your contract?
+* What do you need to consider if there are other projects in your organization integrating with Auth0? Particularly projects that target their own, or a different domain of users (for example, applications that only employees will use)?
+<% if (platform === "b2b") { %>
+* How can you align the structure and domain of your customers’ organization with your Auth0 deployment?
+<% } %>
+
+Organizations often service more than one domain of user - customers, employees, and affiliates being the most frequently encountered, with typically little to no cross-over: employees, say, don’t use the same applications as customers and vice-versa. In some cases there can also be a need to partition further within a domain - separate groups of customers, say, who use different and unconnected products. Auth0 provides a way to segregate your users and the associated collateral, and [tenant provision](#tenant-provision) covers this in more detail. If you need to provision an independent tenant then you’ll also want to [associate this with your existing Auth0 account](#tenant-association), so that you can take full advantage of the benefits provided at your organization’s contracted subscription level.
+
+::: panel Best Practice
+It’s not uncommon for companies to have identity requirements that address multiple user communities: customers, partners, employees, etc. So be sure to consider other projects or future requirements when designing your architecture.
+:::
+
+In addition, you’ll undoubtedly have an established set of processes and procedures as part of your Software Development Lifecycle (SDLC). So you’ll want to check out our [SDLC support](#sdlc-support) guidance regarding Auth0 Tenant provision in support of that too.
+
+For customer-facing applications, we typically see [OpenID Connect (OIDC)](/protocols/oidc) as being the most frequently used protocol. OIDC makes use of web based workflows with browser URLs that are presented to the user. Out-of-the-box, client facing URLs as part of Auth0 OIDC support are Auth0 branded, however we recommend using the Auth0 [custom domain](#custom-domains) capability to provide for consistent corporate identity and to also address potential user confidence concerns before they arise.
+
+::: panel Best Practice
+Other groups within your organization may also be working with Auth0; it’s not uncommon for our customers to have disparate departments that serve different user communities. Identifying these will potentially influence your design choices, and doing so early could mitigate decisions that might prove costly later on.
+:::
+
+<% if (platform === "b2b") { %>
+If your customers' organizations support the use of multiple IdPs, then we recommend that you can create separate Auth0 tenants for that organization; see [Tenant provision for complex organizations](#tenant-provision-for-complex-organizations) for further details. This allows you to keep the rest of your setup much simpler by maintaining a one-to-one connection relationship between your organization and all your customer organizations within your main tenant.
+<% } %>
+
+::: panel Get Started with Auth0 Video
+Watch this short video [Architecture: Your Tenant](/videos/get-started/01-architecture-your-tenant) to learn what an Auth0 tenant is and how to configure it in the Auth0 Dashboard. Understand why you may want more than one tenant if you have different user communities, and also how you can use more than one tenant to support your Software Development Life Cycle (SDLC). Understand the importance of tenant naming and custom domain usage best practices. Also learn how to set up additional tenant administrators and how to associate tenants with your Auth0 account.
+:::
\ No newline at end of file
diff --git a/articles/architecture-scenarios/_includes/_architecture/_sdlc-support.md b/articles/architecture-scenarios/_includes/_architecture/_sdlc-support.md
new file mode 100644
index 0000000000..bddb0fea0d
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_architecture/_sdlc-support.md
@@ -0,0 +1,17 @@
+Every company has some form of Software Development Life Cycle (SDLC), and throughout the development process you will want to align with that strategy. For instance, you need to be able to test your integration with Auth0 in a similar fashion as you test the applications themselves. It is therefore important to [structure Auth0 tenants to support your SDLC](/dev-lifecycle/setting-up-env), and there is a consistent pattern which our customers typically follow when it comes to the best practices associated with tenant layout for doing so:
+
+| Environment | Sample Tenant Name | Description |
+| - | - | - |
+| Development | **company-dev** | A shared environment where most of your development work occurs |
+| QA/Testing | **company-qa** or **company-uat** | An environment for formal testing of the changes you've made |
+| Production | **company-prod** | The production tenant |
+
+In some cases you may also want to create one or more sandboxes (e.g., **company-sandbox1**, **company-sandbox2**) so that you can test changes without compromising your development environment. This might be where you test deployment scripts and the like.
+
+::: panel Best Practice
+You can also take advantage of our [Implementation Checklists](/architecture-scenarios/checklists) that you can download and customize to meet your implementation project needs.
+:::
+
+::: warning
+Though Auth0 allows you to create as many free tenants as you'd like, you may be limited for the number of tenants where all paid features are enabled. If elegible, you can be provided with up to **three** tenants where all features are shared.
+:::
diff --git a/articles/architecture-scenarios/_includes/_architecture/_tenant-association.md b/articles/architecture-scenarios/_includes/_architecture/_tenant-association.md
new file mode 100644
index 0000000000..dc2739a4cf
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_architecture/_tenant-association.md
@@ -0,0 +1 @@
+To ensure that your [tenants are all associated with your Auth0 contractual agreement](/dev-lifecycle/child-tenants) and have the same features, ensure all your tenants are associated with your company account. If you have individual developers that want to create their own sandboxes for testing, make sure they get associated with your account so they have the same permissions too. To do this you should contact your Auth0 representative or the Auth0 Support Center at ${env.DOMAIN_URL_SUPPORT}.
diff --git a/articles/architecture-scenarios/_includes/_architecture/_tenant-provision.md b/articles/architecture-scenarios/_includes/_architecture/_tenant-provision.md
new file mode 100644
index 0000000000..f502ca08a7
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_architecture/_tenant-provision.md
@@ -0,0 +1,7 @@
+Everything starts with an Auth0 tenant. This is where you will be configuring your use of Auth0, and the where Auth0 assets - such as [Applications](/applications), [Connections](/connections) and [user profiles](/architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt) are defined, managed and stored. Access to an Auth0 tenant is performed via the Auth0 [Dashboard](/dashboard), and via the Dashboard you can also create additional, associated tenants; you’re allowed to create more than one Auth0 tenant so that you can structure your tenants in a way that will isolate different domains of users and also support your [Software Development Life Cycle](#sdlc-support) (SDLC).
+
+::: warning
+Tenant names cannot be changed, nor reused once deleted. So, make sure you're happy with your name(s) before you create your Auth0 tenants.
+:::
+
+Determining the level of isolation you require when it comes to your user domains is an important step, and together with your branding requirements will subsequently help you determine the number of Auth0 tenants that will be required in your production environment. As we recommend you create a full suite of [SDLC supporting tenants](#sdlc-support) for every Auth0 tenant you will run in a production environment, the number of Auth0 tenants you will need to manage can quickly grow. Therefore you should consider carefully before creating multiple Auth0 tenants for production, and should consult our guidance on [Branding](/architecture-scenarios/implementation/${platform}/${platform}-branding) before making your final decision.
diff --git a/articles/architecture-scenarios/_includes/_authentication/_application-integration.md b/articles/architecture-scenarios/_includes/_authentication/_application-integration.md
new file mode 100644
index 0000000000..8580bb8809
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_application-integration.md
@@ -0,0 +1,60 @@
+Once you've figured out how you want to authenticate your users, the next step is to determine how you will initiate that authentication. Each application will typically have its own starting point.
+
+::: warning
+Native mobile applications (and desktop applications) should use the system browser for authentication, or they open themselves up to additional security risks. See [Native vs. Browser Login on Mobile](/design/browser-based-vs-native-experience-on-mobile) for more information.
+:::
+
+As discussed, we've found that most of our customers use [OpenID Connect (OIDC)](/protocols/oidc) as the industry-standard protocol when it comes to their customer-facing applications. Figuring out which [OIDC flow](/api-auth/intro) to use is your first task, and you will want to start by reviewing the our [grant mapping](/applications/reference/grant-types-auth0-mapping) guidance in the first instance.
+
+If you want to allow anonymous users access to any part of our application then you need to determine if you will be redirecting right away or prompting your users to redirect only when required (or perhaps some combination of both; see [Redirect Users After Login Authentication](/users/guides/redirect-users-after-login) for further discussion). If users can [deep link](#deep-linking-to-protected-endpoints) to a protected version (or area) of your site then you will need to determine the links to your application that will result in an automatic redirect to Auth0.
+
+### Anonymous access
+
+It is important to consider the user experience when someone first comes to your application. If your application supports anonymous user access (quite common for eCommerce applications) there are different scenarios to consider:
+
+* Are they returning to the application after having already logged in, or
+* If this is the first time they are accessing the application:
+ * Have they already accessed a different application that uses the same Auth0 tenant,
+ * Have they ever (or perhaps not in a long time) authenticated on this device or browser.
+
+When an anonymous user accesses your application, it can often be desirable for the application to discover if the user has already logged into a different application in the same family, or to remember this user even if the application is a [SPA](/quickstart/spa) with no state. For example, if you can determine that the user is already logged in, you might decide to have the UI header in the application skip displaying a login button and instead have an account or profile menu for the user. To accomplish this you will want to utilize "[silent authentication](/api-auth/tutorials/silent-authentication)". Silent authentication will allow you to check to see if the user is logged in without prompting them to log in if they are not. Then the application can present a login button if necessary. If the user is logged in already, however, then you will receive tokens and will not have to present the user with a login button again.
+
+::: warning
+Checking for a login session by redirecting to Auth0 can be really helpful for your application, but if this will result in a lot of requests it is important to employ some sort of throttling mechanism to avoid latency and/or rate limiting. <%= include('../../_includes/_rate-limit-policy.md') %>
+:::
+
+### Deep linking to protected endpoints
+
+There are a variety of reasons why someone might link directly to a particular page within your application that is only accessible by authenticated users. If this is possible for your application you should automatically redirect your user to Auth0 if they are not authenticated. Once they authenticate and the authorization server returns them to your application, you can [redirect them](/users/guides/redirect-users-after-login) to where they intended to go in the first place.
+
+::: panel Best Practice
+Most modern authentication frameworks support middleware for redirecting to an authorization server such as Auth0. Ensure yours:
+
+* Is configurable
+* Can check expirations
+* Supports Refresh Tokens (for confidential clients)
+:::
+
+### Authenticating the user
+
+Authentication is the process of determining user identity. The result of authentication in an OIDC context is an ID Token. This token contains information about the user and should only be able to be obtained if the user authenticates using one or more factors as defined by the authorization server (the most common form being [user ID and password](#username-and-password-authentication)). There are a few things you may also need to consider in addition to obtaining an ID Token:
+
+* Do we also need an [Access Token](/tokens/concepts/access-tokens) in order to call a shared API?
+* Is your application a single-page application and only requires an [ID Token](/tokens/concepts/id-tokens)? See [Implicit Grant](/api-auth/tutorials/implicit-grant) for more information.
+* Is your application a native application (mobile or desktop) and/or do you need a [Refresh Token](/tokens/concepts/refresh-tokens)? See [Authorization Code Grant with PKCE](/api-auth/tutorials/authorization-code-grant-pkce) for more information.
+
+::: warning
+Before you go live, you should ensure that **only** the grants that you are using for each application are enabled in your [configuration for your Application](/dashboard/guides/applications/update-grant-types).
+:::
+
+### Implicit grant
+
+If all your application needs is the ID Token and the application is browser-based, then you can always use the [implicit grant](/api-auth/tutorials/implicit-grant) to get your ID Token. This is a simple authentication flow and should be supported by your SDK (depending on the language you are developing in).
+
+::: warning
+If you need a [Refresh Token](/tokens/concepts/refresh-tokens) so that you can obtain a new Access Token or ID Token without having to re-authenticate the user, then you must use the [authorization code grant](/api-auth/tutorials/authorization-code-grant).
+:::
+
+### Authorization code grant (with or without PKCE)
+
+If your SDK only supports the Authorization Code grant, or you need an Access Token or Refresh Token, then Authorization Code grant (with or without [PKCE](/flows/concepts/auth-code-pkce)) can also be used to retrieve an ID Token. The Authorization Code grant includes an additional API call to exchange the code for a token which can result in additional unnecessary latency if all you need is the ID Token. In many cases the [hybrid flow](/api-auth/tutorials/hybrid-flow) is implemented to provide optimum access to the ID Token while still leveraging Authorization Code grant workflow for the secure and safe retrieval of Access and Refresh Tokens.
diff --git a/articles/architecture-scenarios/_includes/_authentication/_attack-protection.md b/articles/architecture-scenarios/_includes/_authentication/_attack-protection.md
new file mode 100644
index 0000000000..42aeb1a83b
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_attack-protection.md
@@ -0,0 +1,5 @@
+The reason that authentication systems are important is to prevent bad actors from accessing applications and user data that they should not. We want to place as many barriers as possible between those bad actors and access to our systems. One of the easiest ways to do this is to ensure that your [attack protection](/attack-protection) with Auth0 is configured correctly, so take a moment to read the guidance on this subject and ensure that it's working correctly for you.
+
+::: panel Best Practice
+Attack protection is handled behind the scenes by Auth0 and provides a great security feature for your product. If you're going to utilize it, ensure that you have set up your [Email Provider](/architecture-scenarios/implementation/${platform}/${platform}-operations#email-provider-setup) and configured your [Email Templates](/architecture-scenarios/implementation/${platform}/${platform}-branding#email-template-customization) before turning on email delivery to your users.
+:::
diff --git a/articles/architecture-scenarios/_includes/_authentication/_introduction.md b/articles/architecture-scenarios/_includes/_authentication/_introduction.md
new file mode 100644
index 0000000000..1921e46883
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_introduction.md
@@ -0,0 +1,46 @@
+In order to provide services to your users, you must be able to identify who those users are. This process is called User Authentication. There are a number of ways to perform authentication of a user - via social media accounts, username and password, passwordless - and it's often recommended that you go beyond a first factor for authenticating the user by enabling multi-factor authentication (MFA).
+
+::: panel Best Practice
+It's important to consider both security and user experience when designing how you will authenticate your users. Providing for multiple primary factors, and/or enforcing more than one factor during authentication, are ways that you can provide both.
+:::
+
+There are a number of things you will want to consider when looking at functionality and workflow:
+
+* Where will users enter their credentials?
+* How will you keep user credentials safe?
+* How will you maintain your authentication system?
+* How can you provide password authentication for your users?
+* How can you prevent hackers from trying to log in as your users?
+* How will you implement authentication in different kinds of applications?
+* How can you make login easy for your users when they come from different language backgrounds?
+* How will you provide a good user experience as you migrate away from any legacy authentication system?
+* What should you consider when integrating applications with Auth0?
+<% if (platform === "b2c") { %>
+* Can users log in using their existing social (e.g., Facebook or Google) accounts?
+<% } %>
+* Do you need to provide multi-factor authentication?
+* What do you do if you have a service that doesn't have a way for the user to log in ahead of time?
+* Can you pass the same user access token from one API to another?
+<% if (platform === "b2b") { %>
+* What do you do if you need to isolate users by organization?
+* How will you handle identifying which organization users belong to?
+* What’s the benefit of providing enterprise connections for your organizations?
+<% } %>
+
+Auth0 [Universal Login](#universal-login) provides users with a safe and secure experience - no matter whether you choose to provide for user ID/password credentials sign in, or allow the so-called Bring Your Own Identity scenarios provided via [Social Login](https://auth0.com/learn/social-login/). There are also brand recognition benefits to centralizing the login experience with Universal Login, even if you feel you will also have product-specific [branding](/architecture-scenarios/implementation/${platform}/${platform}-branding) requirements. The Auth0 UI widgets typically used with Universal Login also provide out-of-the-box support with regards to [internationalization](/libraries/lock/v11/i18n) for users with different language requirements, and out-of-the-box support for Auth0 features such as [MFA](#multi-factor-authentication-mfa-) and [attack protection](#attack-protection) allow you to put barriers in place in order to prevent hackers attempting to access users' accounts.
+
+Allowing users to sign in via user ID/password credentials means that you're not reliant on the status of third-party identity providers for your users to access your system. You also have the means require the credentials used to align with your corporate policies. Auth0 assists with this by providing you with multiple options in support of user ID/password logins, and the [guidance provided](#username-and-password-authentication) will help you understand you can leverage these options. Adding [social](#social-authentication) support at some stage, as an additional primary authentication factor, gives you added flexibility and can help you better understand your users without the need to question them further by leveraging the information already stored by the various social login [providers](/connections/identity-providers-social).
+
+If you have an existing legacy identity store, you’ll also want to see [User Migration](/architecture-scenarios/implementation/${platform}/${platform}-provisioning#user-migration). This section discusses the advantages of migrating to Auth0’s managed identity storage in terms of safety and security.
+
+For customer facing applications, OpenID Connect ([OIDC](/protocols/oidc)) is the most frequently used industry standard protocol, and OIDC has first-class citizen support in Auth0. Auth0 provides support for various different approaches for integrating various different applications, so you'll want to see the section on [application integration](#application-integration) for the information you'll need to make an informed choice.
+
+When calling one API from another API, or from any situation where there is no authenticated user context - such as one or more cron jobs, report generators, or continuous integration/delivery systems - you will need a way to authorize the _application_ instead of a _user_. This is a one step process where the application is authenticated (using a client ID and secret) and then authorized in one call. You can learn more about this in our authorization workstream under [machine-to-machine (m2m) authorization](/architecture-scenarios/implementation/${platform}/${platform}-authorization#machine-to-machine-m2m-authorization).
+
+<% if (platform === "b2b") { %>
+Often companies need to segregate their users by organization and sometimes users can have access to more than one organization. Knowing which of these scenarios is relevant to your company will help define how to determine in which connection a user exists: whether you need to do it, when you need to do it, and how to accomplish it. See [Home Realm Discovery](#home-realm-discovery) to determine if this is something relevant to your company.
+<% } %>
+
+::: panel Get Started with Auth0 Videos
+Watch these two short videos [Authenticate: How It Works](/videos/get-started/04_01-authenticate-how-it-works) and [Authenticate: SPA Example](/videos/get-started/04_01-authenticate-spa-example) to learn about the differences between authentication, authorization, and access control. Understand when and why you might use each type of authentication method: first factors, second factors, and multi-factor. Learn about the OpenID Connect (OIDC) authentication protocol. See an example using the Auth0 Quickstart for a single-page application (SPA) implementation.
+:::
diff --git a/articles/architecture-scenarios/_includes/_authentication/_mfa.md b/articles/architecture-scenarios/_includes/_authentication/_mfa.md
new file mode 100644
index 0000000000..ec67e73549
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_mfa.md
@@ -0,0 +1,16 @@
+In an era where misuse of user credentials is at an all-time high, protecting _your_ systems when it’s so common for hackers to steal users identity information in general is a challenge. One of the most effective ways though is to provide users with the ability to configure a second factor for protecting their account. More commonly referred to as [Multi-Factor Authentication](/mfa). This will ensure that only a valid user can access their account, even if they use a username and password that may have been compromised from a different application.
+
+::: panel Best Practice
+It's quite common for customer facing applications to provide users with an _option_ for adding a second factor rather than _forcing_ them to use a second factor. For more information regarding this, see [providing your users with an option to add MFA](https://auth0.com/learn/multifactor-authentication-customers/).
+:::
+
+Auth0 supports a number of different options when it comes to enabling MFA for protecting user account access, and there are several practices to ensure that you will truly be providing a flexible second factor barrier to access:
+
+* Auth0 [Guardian](https://auth0.com/multifactor-authentication): a service that provides both _Push_ notification generation and an application for allowing or denying requests. _Push_ sends notification to a user’s pre-registered device - typically a mobile or tablet - from which a user can immediately allow or deny account access via the simple press of a button.
+* Time-based One-Time Password (TOTP): allows you to register a device - such as Google Authenticator - that will generate a one-time password which changes over time and which can be entered as the second factor to validate a user’s account.
+* SMS: for sending a one-time code over SMS which the user is then prompted to enter before they can finish authenticating.
+* Voice: for delivering a one-time code through a phone call which the user is then prompted to enter before they can finish authenticating.
+* Duo: allows you to use your Duo account for multi-factor authentication.
+* Email: allows you to use your email account for multi-factor authentication.
+
+Whilst MFA workflow using technologies such as Guardian or Google Authenticator is typically provided via a separate application that runs on a mobile or tablet device, if you don’t want your customers to have to download a separate application Auth0 also provides you with an SDK that you can use to build second factor workflow right in your existing mobile device application(s).
diff --git a/articles/architecture-scenarios/_includes/_authentication/_social-authentication.md b/articles/architecture-scenarios/_includes/_authentication/_social-authentication.md
new file mode 100644
index 0000000000..262ba3477c
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_social-authentication.md
@@ -0,0 +1,13 @@
+The “bring your own identity” scenario offered by Facebook, Google, etc., is a valuable way of simplifying the user authentication experience without compromising security, and using [Universal Login](#universal-login) makes it easy to start adding support for [Social Connections](/connections/identity-providers-social) with minimal disruption.
+
+::: warning
+Auth0 provides a simple way to test social connections using [pre-configured developer keys](/connections/social/devkeys). However, these have [limitations](/connections/social/devkeys#limitations-of-developer-keys), and before going into production, you’ll need to set up your own application-specific keys by following the [instructions](/connections/identity-providers-social) for your chosen social provider(s).
+:::
+
+With [social](https://auth0.com/learn/social-login/) support, user identities and credentials are managed by the social provider, as are certain identity claims—which Auth0 will use to populate the user [profile](/architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt). Auth0 can also provide access to Social Identity Providers' (Social IdPs') [Access Tokens](/tokens/overview-idp-access-tokens), so that your application can also call 3rd-party Social IdP APIs on behalf of the user.
+
+::: panel Best Practice
+Social is a great feature to provide, but when you offer more than one way to sign in, you need to consider the possibility that your customers will actually use more than one way to sign in. By default, every user identity in Auth0 has its own user profile, so you’ll probably want to consider Auth0's capability to [link user accounts](/users/concepts/overview-user-account-linking) to provide an effective way of associating one user profile with multiple identities.
+:::
+
+Auth0 [Custom Social Connections](/connections/social/oauth2) extend social authentication even further by allowing you to connect with any OAuth2 identity provider not supported out-of-box. For example, support for the government-issued-identity provider [SwissID](https://www.swissid.ch/) can be configured in Auth0 by using a Custom Social Connection.
diff --git a/articles/architecture-scenarios/_includes/_authentication/_sso-legacy.md b/articles/architecture-scenarios/_includes/_authentication/_sso-legacy.md
new file mode 100644
index 0000000000..58df288183
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_sso-legacy.md
@@ -0,0 +1,10 @@
+In a large scale re-structure it's not always possible—or practical—to update all your applications at once. In fact, our recommended best practice is to plan for an iterative-style approach when it comes to integrating with Auth0. If your applications already participate in Single Sign-on (SSO), and your legacy identity system supports protocols such as OIDC or SAML, then you have a couple of options available if you want to continue to provide SSO as you integrate with Auth0:
+
+* Update your existing identity provider in your legacy SSO system to redirect to Auth0 for login (e.g., using [SAML](/protocols/saml/saml-configuration/auth0-as-identity-provider)), or
+* Have Auth0 redirect to your legacy SSO system to login. This requires configuring your legacy system as an IdP in Auth0 (i.e., either using [SAML](/protocols/saml/saml-configuration/auth0-as-service-provider) or [OIDC](/connections/social/oauth2)).
+
+::: panel Best Practice
+Supporting an SSO experience with your legacy system can add complexity, but may be worth it to generate a more seamless user experience as you integrate with Auth0. If you intend to go down this path, planning for it early can help ensure that it is possible to achieve. If you don't already have SSO at a centralized service, then the complexity to add it will unlikely be worth the benefits.
+:::
+
+This is a complex topic that will likely need some additional investigation depending on your current legacy architecture, and we recommend you only look into this if you currently have SSO support in your legacy system. Note: if you are currently redirecting from your applications to a centralized system to authenticate your users and that system only asks for credentials if you don’t already have a session with the centralized system, then you have a legacy SSO implementation.
diff --git a/articles/architecture-scenarios/_includes/_authentication/_universal-login.md b/articles/architecture-scenarios/_includes/_authentication/_universal-login.md
new file mode 100644
index 0000000000..57dc6a92d7
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_universal-login.md
@@ -0,0 +1,11 @@
+Do you have, or will you have, more than one application in your system? If the answer to this question is yes, then you will want a centralized sign in experience. To achieve a seamless Single Sign-on (SSO) experience between multiple applications, it is critical to have a centralized location to redirect your users for authentication. This allows you a way to provide your users with a consistent experience if you add social authentication in the future, add third party applications to your system, or add multi-factor authentication as an option (or requirement) for your users - and also allow you to take advantage of new features for improving your users’ experience with little, if any, added development effort.
+
+::: panel Best Practice
+If you have more than one application, the best practice is to redirect to a [centralized location](/universal-login) to authenticate the user. With Auth0, this means taking advantage of [Universal Login](/universal-login), which provides many security and user experience benefits out-of-the-box, including [SSO](/sso/current).
+:::
+
+Auth0 Universal Login makes authenticating users a short, easy process which can be accomplished in three easy steps (all of our Quickstarts demonstrate this and our SDKs hide the complexity for you too):
+
+1. Determine how and when you want to [redirect from your application](#application-integration).
+2. Set up the appropriate [branding](/architecture-scenarios/implementation/${platform}/${platform}-branding) and/or customized HTML in your Auth0 configuration.
+3. Set up your application to [receive and handle the response](#application-integration) from the Authorization Server.
diff --git a/articles/architecture-scenarios/_includes/_authentication/_username-and-password-authentication.md b/articles/architecture-scenarios/_includes/_authentication/_username-and-password-authentication.md
new file mode 100644
index 0000000000..6668a0c76d
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authentication/_username-and-password-authentication.md
@@ -0,0 +1,9 @@
+Nearly every B2C application provides the ability for their customers to create a new set of credentials. This is a common form of authentication that all users are familiar with.
+
+Username password authentication comes in multiple flavors at Auth0. If your application is a green-field application with no existing user base, then a simple Auth0 out-of-the-box [Database Connection](/connections/database) will give you everything you need to start authenticating your users. However, if you have a legacy user store (such as your own database of users or an existing LDAP system) you have a couple of different options for migrating your users as discussed in our guidance on [User migration](/architecture-scenarios/implementation/${platform}/${platform}-provisioning#user-migration).
+
+However you end up provisioning the users for your database connection, the authentication of those users is quite similar. It requires you to present users with a form to enter their username and password. As mentioned in the guidance concerning [Universal Login](#universal-login), the simplest and safest way to authenticate users with a username and password is to redirect them to a centralized login page and collect their username and password there. This allows Auth0 to determine whether they have already authenticated and skip the login form entirely when it's not needed.
+
+::: panel Best Practice
+Collecting credentials only at the centralized login page will reduce the surface area for potential leak of user secrets. It will also reduce the need to collect credentials unnecessarily. See [Universal Login](#universal-login) for more information.
+:::
diff --git a/articles/architecture-scenarios/_includes/_authorization/_api-integration.md b/articles/architecture-scenarios/_includes/_authorization/_api-integration.md
new file mode 100644
index 0000000000..879f473836
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authorization/_api-integration.md
@@ -0,0 +1,37 @@
+In this scenario your Auth0 tenant can provide an OAuth2 [Access Token](/tokens/concepts/access-tokens), typically expressed as a [JWT](/tokens/concepts/jwts), which [can be used by your API to restrict access to certain parties](/api-auth). In addition, Auth0 provides support for what is notionally described as both [First-Party and Third-Party Applications](/applications/concepts/app-types-first-third-party).
+
+Acting as the authorization server, and with the consent of the user (the resource owner), your Auth0 tenant can be used to provide an Access Token - typically expressed as a [JWT](/tokens/concepts/jwts) - to an application (client) so that it can access a protected resources hosted by a resource server on behalf of the resource owner. The issued Access Token is typically passed as the Bearer token in the HTTP Authorization header sent to an API.
+
+Whether you have a single API, or perhaps a suite of logically related [microservice APIs](/api-auth/tutorials/represent-multiple-apis), you can leverage the Access Tokens that Auth0 provides in order to secure access to your service(s). Though relatively easy to set this up in the [Auth0 Dashboard](/apis) or through the [Auth0 Management API](/api/management/v2#!/Resource_Servers/post_resource_servers), it's important to review the different application scenarios and API layouts to determine the best architecture for your system.
+
+::: note
+OAuth2 Access Tokens are primarily designed for use in securing public facing APIs; when expressed as a JWT, an Access Token is a self contained entity which can be verfied without the need to make any additional 3rd party API call. If your APIs do not fall into this category - i.e they are part of an application itself (as in only called by that application) or are sat behing your firewall - then protecting them with tokens may well be overkill, and your existing cookie based (et al) workflow may well suffice.
+:::
+
+OAuth2 was designed specifically with third-party access in mind, For example, a scenario might be that a user (resource owner) wants to use an application (a client) that does not belong to the same organization as the service that provides the user's data (the reseource server). In this case, when the application needs to access data that the user owns, it redirects to the organization where the user’s data resides, which in turn authenticates the user and then prompts the user to give the application permission to access their data. This prompting for permission is referred to as providing *[consent](/api-auth/user-consent)* and is a large part of what providing support for [third party applications](/scopes/current/api-scopes#example-an-api-called-by-a-third-party-application) entails. If you are planning to integrate third-party applications, then it's important you [mark them as third-party](/api-auth/user-consent) early on so that Auth0 will handle prompting for user consent.
+
+On the other hand, if your organization *owns* the application(s), the user data itself and the API(s) through which that data is accessed, then consent is not typically required as the interactions are all [first-party](/scopes/current/api-scopes#example-an-api-called-by-a-first-party-application). If you're only creating first-party applications, then you can ensure that you are not presenting your users with any unnecessary consent screen(s) by [allowing user consent to be skipped](/apis#api-settings) as part of any resource service definition.
+
+::: warning
+Though you can configure your applications to be first-party and subsequently configure your APIs to allow first-party clients to ignore consent, if you are using `localhost` then Auth0 cannot verify that the application is truly a first-party app so your users will be prompted for consent anyway. To work around this constraint, when testing on your local machine during development, create a [fake local hostname and use that instead](https://community.auth0.com/t/how-do-i-skip-the-consent-page-for-my-api-authorization-flow/6035).
+:::
+
+Alternatively, you may have data relating to a user for which additional [functionality is provided](/scopes/current/api-scopes#example-an-api-called-by-a-back-end-service) and for which explicit user consent cannot be obtained (i.e. there is no authenticated user who can provide it). In this scenario, a [list of applications for which Client Credentials grant is enabled](/flows/concepts/client-credentials) can be defined.
+
+### Access Token claims
+
+As is the case with ID Tokens, you can [add custom claims to Access Tokens](/scopes/current/sample-use-cases#add-custom-claims-to-a-token) using Auth0 Rule extensibility. Once added, your API can then verify an Access Token for the necessary claims and either allow or prevent access to certain functionality as required.
+
+::: panel Best Practice
+When you are considering adding custom claims, we recommend that you store any access control data you may need to include within claims as part of the user's [`app_metadata`](/users/concepts/overview-user-metadata). Firstly, this prevents you from needing to call an external API to fetch the data, which can negatively impact performance and scalability. Secondly `app_metadata` **cannot** be modified by a user - so the user cannot directly circumvent any access control restrictions by modifying their own metadata. Also remember to check out our [metadata best practices](architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt#metadata) guidance too.
+:::
+
+### Access Token scopes
+
+[OAuth2 Scopes](/scopes/current/api-scopes) are typically used as the mechanism by which an API can determine what actions can be performed on behalf of a user. Scopes can be added on a per API basis to [define specific access permissions](/dashboard/guides/apis/add-permissions-apis) in the Auth0 Dashboard or through the Auth0 Management API). Scopes can also be manipulated via Auth0 extensibility (e.g. via a Rule, as in this [example](/architecture-scenarios/spa-api/part-2#create-a-rule-to-validate-token-scopes)). The scopes an application requests for accessing an API should depend on what functionality the application needs the user to give permission for the application to use. Once the requested scopes are authorized, they will be returned in the Access Token which can be subsequently verified by said [API](/tokens/guides/validate-access-tokens). A good example of this is when you log in to an application that is using a social provider for login: the social provider API requires that the application specifies whether the user will want the application to post items on your behalf. This allows the user to accept or deny this request. This example demonstrates how the user is delegating permission to the application - which is different than the API restricting access based on a user's role, and should be handled differently.
+
+::: panel Best Practice
+Even though you have the ability to fully manipulate Access Token Scopes via Auth0 extensibility, as a security best practice you should only remove scopes which are not authorized and refrain from adding scopes that were not requested.
+:::
+
+Though scopes are often used as a way to enforce access permissions for a user, there are situations where it can become tricky when you use them in this manner. We therefore recommend that you use scopes for their intended purpose (i.e. delegating permission to an application) and use [custom claims](#access-token-claims) for your role-based or other access control scenarios.
diff --git a/articles/architecture-scenarios/_includes/_authorization/_application-integration.md b/articles/architecture-scenarios/_includes/_authorization/_application-integration.md
new file mode 100644
index 0000000000..bf785f09e1
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authorization/_application-integration.md
@@ -0,0 +1,17 @@
+In this scenario, your Auth0 tenant provides a token as an indicator of authorized access to an application. For applications utilizing [OpenID Connect (OIDC)](/protocols/oidc), the industry-standard protocol we typically find most utilized when it comes to customer facing applications, this would be an ID Token expressed as a [JWT](/tokens/concepts/jwts).
+
+### ID Token claims
+
+Using Rule extensibility, Auth0 allows you to easily [add custom claims to an ID Token](/scopes/current/sample-use-cases#add-custom-claims-to-a-token) based on, for example, a user’s [Metadata](/users/concepts/overview-user-metadata) content. Your application can then verify the ID Token for the necessary claims, and either allow or prevent access to certain functionality as required. Note that though the process of adding custom claims via Rule is streamlined, the Rule engine is flexible and allows you to write custom code that may have negative effects. Therefore it’s important to follow our [rules best practice](/best-practices/rules) guidance anytime you use this extensibility feature.
+
+::: panel Best Practice
+When you are considering adding custom claims, we recommend that you store any access control data you may need to include within claims as part of the user's [`app_metadata`](/users/concepts/overview-user-metadata). Firstly, this prevents you from needing to call an external API to fetch the data, which can negatively impact the performance and scalability of the login sequence. Secondly `app_metadata` **cannot** be modified by a user - so the user cannot directly circumvent any access control restrictions by modifying their own metadata. Also remember to check out our [metadata best practices](architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt#metadata) guidance too.
+:::
+
+<% if (platform === "b2b") { %>
+If you are creating different instances of your application for your customer organizations, a common practice is to create a custom claim in your ID token to represent the user's organization. For example, `context.idToken["http://yourdomain.com/claims/organization"]= "organization A";`
+<% } %>
+
+### ID Token scopes
+
+[OIDC Scopes](/scopes/current/oidc-scopes) are typically used by an application to obtain consent for authorized access to a user's details during authentication. Each of the pre-defined scopes returns the set of [standard claims](/scopes/current/oidc-scopes#standard-claims) where defined, and as described in the [OIDC specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). The scopes an application requests depend on which user attributes the application needs. Once the requested scopes are authorized by the user, the claims are returned in the ID Token and are also made available via the [/userinfo](https://auth0.com/docs/api/authentication#get-user-info) endpoint.
diff --git a/articles/architecture-scenarios/_includes/_authorization/_introduction.md b/articles/architecture-scenarios/_includes/_authorization/_introduction.md
new file mode 100644
index 0000000000..b1720ae98f
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authorization/_introduction.md
@@ -0,0 +1,47 @@
+Let's start by taking a step back and talking about Access Control. There isn't one clear cut definition of Access Control in the industry, but if you spend some time searching and reading you'll see that most authoritative sources agree that it is the umbrella concept that puts all of Authentication, Authorization, Consent, and Policy Enforcement together to ensure that only the right people and services have access to your applications and APIs. Next, let's look more closely into the distinctions between Authentication, Authorization, Consent, and Policy Enforcement. Your Auth0 tenant (your Authorization Server) is typically responsible for Authentication and Consent, and some or all of Authorization and Policy Enforcement. Additionally, an Application or API itself almost always is the primary enforcer of policies, especially where contextual access is required:
+
+* **Authentication**: the process of determining if a principal (a user or application) is who or what they say they are.
+* **Authorization**: the process of determining what is allowed, based on the principal, what permissions they have been given, and/or the set of contextually specific access criteria.
+* **Consent**: what permissions the user (Resource Owner) has given permission to an application to do on its behalf. This is generally a requirement of delegated authorization. The user has to give permission to the Client to access the user's data in a different system.
+* **Policy Enforcement**: The act of enforcing the policies of the application or API, rejecting or allowing access based on a user's authentication and/or authorization information.
+
+In general we typically group different types of access control into three distinct categories so that it's easier to understand a) which actor is responsible for storing the information, b) which actor is responsible for making decisions, and c) which is responsible for enforcing the restrictions.
+
+* The first category is where access is either granted or denied to an application or an API in its entirety. Both the data required to enforce this and the enforcement process is typically defined in the context of the Authorization Server For example, by using [`app_metadata`](/users/concepts/overview-user-metadata) associated with a user and a [Rule](/rules) defined in your Auth0 tenant.
+
+* The second category is where access is either granted or denied to a specific subset of application or API functionality. The data required to enforce this is typically stored in the Authorization Server For example, by using [`app_metadata`](/users/concepts/overview-user-metadata) on a user in your Auth0 tenant with the enforcement process performed in the application or API itself. In this scenario, the data is typically communicated as one or more custom claims in an [`id`](/tokens/concepts/id-tokens) or [`access`](/tokens/concepts/access-tokens) token.
+
+* The third category is where access is either granted or denied depending on what the principal (subject) can operate on within the context of an application or API. Both the data required to enforce this, and the enforcement process is typically defined in the context of the application or API. In this scenario, the data communicated as one or more custom claims in an [`id`](/tokens/concepts/id-tokens) or [`access`](/tokens/concepts/access-tokens) token may be consumed with or without data from an external source that is not Auth0.
+
+In addition, Role-based Access Control (RBAC) and Attribute-based Access Control (ABAC) mechanisms can be applied in any of the Access Control categories described above. Whatever your use case then, there are a number of things you will want to consider when looking at the functionality and workflow you require:
+
+* Are there scenarios where access to an entire application or API should be rejected?
+* Will you be providing APIs that can be accessed by third-party applications?
+* Will your APIs also be accessed by your own (first-party) applications?
+* Will your application be calling a third-party API?
+* Should your applications and/or APIs be enforcing access control based on user claims?
+<% if (platform === "b2b") { %>
+* What if I need to know which organization an access token or id token is associated with?
+<% } %>
+
+Auth0 supports access restriction for either applications or APIs based on certain conditions. In certain scenarios, you may want to create a [Rule](/rules) that returns an `UnauthorizedError` when, for example, a user attempts access to an application or an API at an incorrect time (as described in this [example](/authorization/concepts/sample-use-cases-rules#allow-access-only-on-weekdays-for-a-specific-application)) - or if the user doesn’t have the right claim(s) contained in their [`app_metadata`](/users/concepts/overview-user-metadata). For an _application_ using [OpenID Connect (OIDC)](/protocols/oidc), this would prevent the allocation of the [ID Token](/tokens/concepts/id-tokens) used to authorize access. Similarly, for an _API_, allocation of any OAuth2 [Access Token](/tokens/concepts/access-tokens) (used when calling the API), could be prevented as described in this [example](/api-auth/restrict-access-api#example-deny-access-to-anyone-calling-the-api).
+
+::: panel Best Practice
+In the main, we have found that [OIDC](/protocols/oidc) is the most commonly used industry-standard protocol used by Auth0 customers when it comes to authentication in their applications. We have also found that, even though [OAuth2](protocols/oauth2) was created as a delegation protocol, it is commonly used within first party applications when there is an API that does not have a shared session with the application.
+:::
+
+Auth0 also can provide the information needed so that an application can enforce restrictions. For [application level integration](#application-integration), Auth0 allows you to add [custom claims](#id-token-claims) to an ID Token, which your application can then verify and subsequently use to perform policy enforcement. In this case you will need to decide what information you require for your application to make enforcement decisions. If you need to make decisions at an API instead of in your application, you will likely need to use an Access Token instead of an ID token. Continue reading for more information.
+
+::: warning
+When deciding what data to include in your ID token and/or access token, consider token size, especially if you are passing the token in the URL. Even if you are not passing tokens in the URL, you will also need to consider the potential of exposing sensitive PII (Personally Identifiable Information). Token information is not encrypted, so although it isn't generally a security issue for an ID token to be leaked, it can become a privacy issue depending on the data that is included in the token.
+:::
+
+For [API level integration](#api-integration), Auth0 supports both [custom claims](#access-token-claims) as well as [scope](#access-token-scopes) re-configuration, both within the context of an Access Token. Again, you will need to decide what information will be required in order for your API to make access decisions, and your API will need to enforce that by validating the contents of the Access Token.
+
+::: panel Best Practice
+When deciding whether you should use permissions through custom claims or scopes, you should make sure you understand the nature and purpose of scopes.
+:::
+
+<% if (platform === "b2b") { %>
+For multi-organization scenarios, it can often be important to know which organization an access token (or even an ID token) applies to. Taking care to follow the [best practices](#organization-data-in-an-access-token) can save you time and effort.
+<% } %>
diff --git a/articles/architecture-scenarios/_includes/_authorization/_m2m.md b/articles/architecture-scenarios/_includes/_authorization/_m2m.md
new file mode 100644
index 0000000000..f22d07cc27
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authorization/_m2m.md
@@ -0,0 +1,13 @@
+There are many scenarios that require an application _without_ any user-interactive session to obtain an access token in order to call an API. In such scenarios you must authenticate the client instead of the user, and OAuth 2 provides the [client credentials](/flows/concepts/client-credentials) grant type to make this easy to achieve. Some common examples of where this is required include:
+* A cron job or other service that needs to communicate with your API (e.g. where a daily report needs to be generated and emailed it to an administrator).
+* A separate API the supports privileged access (e.g. the API is not exposed to users directly, but instead to a backend only).
+* In certain microservice architectures, where some API layers need to communicate to other API layers without a user involvement, or after a user token has expired.
+* A privileged API that may need to be called before a user has authenticated (i.e. from a rule or custom DB script in your Auth0 tenant)
+
+::: panel best practice
+Traditionally, a special "service account" would have been created in order to cater for these scenarios: a user with a username and password that was configured for services which supported non-interactive use cases. That is no longer a recommended approach for many reasons, and the current best practice is to use [OAuth 2.0 Client Credentials Grant](/flows/concepts/client-credentials) in these situations.
+:::
+
+::: warning
+Though the [Client Credentials Exchange Hook](/hooks/extensibility-points/client-credentials-exchange) in Auth0 can be used to add custom claims, it's important to consider the purpose for which a token was requested and to avoid extending use of the token beyond its intended purpose. Doing otherwise can result in the creation of unintended attack vectors for attackers to exploit.
+:::
diff --git a/articles/architecture-scenarios/_includes/_authorization/_rbac.md b/articles/architecture-scenarios/_includes/_authorization/_rbac.md
new file mode 100644
index 0000000000..68df646d59
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_authorization/_rbac.md
@@ -0,0 +1 @@
+Auth0 has out-of-box support for Role Based Access Control ([RBAC](/authorization/concepts/rbac)). RBAC refers to assigning permissions to users based on their _role_ within an organization, and provides for simpler access control by offering a more manageable approach that is less prone to error.
\ No newline at end of file
diff --git a/articles/architecture-scenarios/_includes/_base-intro.md b/articles/architecture-scenarios/_includes/_base-intro.md
new file mode 100644
index 0000000000..2dfc169d6e
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_base-intro.md
@@ -0,0 +1,5 @@
+Customers using Auth0 for <% if (platform === "b2c") { %>Business-to-Consumer (B2C)<% } else { %>Business-to-Business (B2B)<% } %> projects typically share a common set of goals and objectives, and in the sections that follow we'll focus on our real-world customer implementation experiences to help you deliver your solution efficiently.
+
+::: panel Best Practice
+Auth0 provides recommendations and best practice suggestions in an *ad hoc* way throughout this guide in panels like this one. You can also obtain detailed guidance regarding specific functionality by speaking with your account representative or a member of our Auth0 [Professional Services](/services) team.
+:::
diff --git a/articles/architecture-scenarios/_includes/_base-ways-to-integrate.md b/articles/architecture-scenarios/_includes/_base-ways-to-integrate.md
new file mode 100644
index 0000000000..7089399c48
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_base-ways-to-integrate.md
@@ -0,0 +1 @@
+There are many different ways Auth0 can be integrated into the <% if (platform === "b2c") { %>CIAM<% } else { %>B2B IAM<% } %> project architecture. Auth0's flexibility comprehensively supports many different use cases however your project may not require all of the capabilities provided by Auth0. Knowing what, when, and how best to implement something will help you focus on completing the necessary tasks at the right time.
\ No newline at end of file
diff --git a/articles/architecture-scenarios/_includes/_branding/_custom-domain-naming.md b/articles/architecture-scenarios/_includes/_branding/_custom-domain-naming.md
new file mode 100644
index 0000000000..ae02a82b67
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_branding/_custom-domain-naming.md
@@ -0,0 +1,15 @@
+By default, the URL associated with your tenant will include its name and possibly a region-specific identifier. For example, tenants based in the US have the a URL similar to `https://example.auth0.com` while those based in Europe have something that is of the fashion `https://example.eu.auth0.com`. A [Custom Domain](/custom-domains) offers a way of providing your users with a consistent experience by using a name that’s consistent with your organization's brand.
+
+::: warning
+Only one custom Domain Name can be applied per Auth0 Tenant, so if you absolutely must have independent domain name branding then you will require an [architecture](/architecture-scenarios/implementation/${platform}/${platform}-architecture) where multiple Auth0 Tenants are deployed to production.
+:::
+
+In addition, Custom Domain functionality offers you complete control over the [certificate management](/custom-domains#certificate-management) process. By default, Auth0 provides standard SSL certificates, but if you configure a custom domain, you can use Extended Validation (EV) SSL certificates or similar to provide the visual, browser-based cues that offer your visitors additional peace of mind.
+
+In general, we see customers having the most success when they use a centralized domain for authentication - this is especially the case if the company offers multiple products or service brands. By using a centralized domain, you can provide end users with a consistent user experience while also minimizing the need to maintain multiple production tenants in Auth0.
+
+<% if (platform === "b2b") { %>
+::: warning
+If your customer organizations will be isolated from each other, and you require that users are presented a login page for each organization via a custom domain URL, then your only option is to create a [separate tenant for each organization](/architecture-scenarios/${platform}/${platform}-architecture#tenant-provision-for-complex-organizations).
+:::
+<% } %>
diff --git a/articles/architecture-scenarios/_includes/_branding/_email-templates.md b/articles/architecture-scenarios/_includes/_branding/_email-templates.md
new file mode 100644
index 0000000000..3b3dccdf63
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_branding/_email-templates.md
@@ -0,0 +1,9 @@
+Auth0 makes extensive use of email to provide both user notifications and to drive the functionality needed for secure identity management (for example, email verification, account recovery, and brute force protections), and Auth0 provides a number of templates for these.
+
+::: note
+Before customizing email templates, please set up your [Email Provider](/architecture-scenarios/implementation/${platform}/${platform}-operations#email-provider-setup).
+:::
+
+Out of the box, the email templates used contain standard verbiage and Auth0 branding. However, you can configure almost every aspect of these templates to reflect the verbiage and user experience you want and make changes to things like the preferred language, accessibility options, and so forth.
+
+Email templates are customized using [Liquid syntax](/email/liquid-syntax). If you are interested in customizing your templates based on user preferences, you will also have access to the [metadata](/users/concepts/overview-user-metadata) located in users' profiles, as well as any specific application metadata too.
diff --git a/articles/architecture-scenarios/_includes/_branding/_error-page.md b/articles/architecture-scenarios/_includes/_branding/_error-page.md
new file mode 100644
index 0000000000..4f74e4757a
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_branding/_error-page.md
@@ -0,0 +1,5 @@
+If there are issues encountered during user interactive workflow (e.g. user sign up or login), Auth0 provides error messages that indicate what the problem is under the hood. The default messages are somewhat cryptic, especially to the end user, since they will likely be missing context that only you can supply. As such, we recommend [customizing your error pages](/universal-login/custom-error-pages) to provide the missing context-specific information directly to your users. Furthermore, customizing your error pages allows you to display your branding, not Auth0's, as well as provide useful information to your users as to what should be done next. This information might include a link to a FAQ or how to get in touch with your company's support team or help desk.
+
+::: panel Best Practice
+Out-of-the-box there is no user interface for customizing Auth0 provided error pages, but you can use the [Tenant Settings endpoint of the Management API](/api/management/v2#!/Tenants/patch_settings) to configure them. Alternatively, if you can create and host your own error page, then you can have Auth0 direct users to that page instead of using the Auth0-hosted option.
+:::
diff --git a/articles/architecture-scenarios/_includes/_branding/_guardian.md b/articles/architecture-scenarios/_includes/_branding/_guardian.md
new file mode 100644
index 0000000000..99b6009f56
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_branding/_guardian.md
@@ -0,0 +1,3 @@
+The Multi-factor Authentication pages can be customized by adjusting the Universal Login branding options in the [Universal Login Settings](${manage_url}/#/login_settings) section.
+
+If you need further customization, you can also customize [the full HTML content](/universal-login/multifactor-authentication#customizing-the-html-for-the-mfa-page) to reflect your organization's particular UX requirements.
diff --git a/articles/architecture-scenarios/_includes/_branding/_introduction.md b/articles/architecture-scenarios/_includes/_branding/_introduction.md
new file mode 100644
index 0000000000..387c2dc354
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_branding/_introduction.md
@@ -0,0 +1,35 @@
+Auth0 can be customized with a look and feel that aligns with your organization's brand requirements and user expectations. Branding Auth0 collateral provides a consistent user experience for your customers, and gives them peace of mind that they’re using a product from a trusted and secure provider.
+
+Auth0 provides support for [internationalization (I18N)](/i18n) and localization (L10N), both of which are important if you work on branding for an international clientele. Out-of-box collateral, such as the Auth0 Lock UI widget, comes ready enabled for multiple language support, with built-in extensibility for adding more languages if what you require [doesn’t already exist](/libraries/lock/v11/i18n).
+
+::: panel Best Practice
+Almost all applications need Internationalization and/or Localization in one form or another. Auth0 makes it easy to add, but you need to account for it up front: retro-fitting localization, for example, can be a painful process if left too late.
+:::
+
+When considering the items you want to brand, as well as how best to brand them, there are a number of things you'll want to review:
+
+* Do you need to brand your login page?
+* Do you need to localize your login page?
+<% if (platform === "b2b") { %>
+* If you are sharing an Auth0 tenant across customer organizations, should you add organization-specific branding to their login experience?
+<% } %>
+* How can you customize emails so that they're not just branded, but vary based on user preference?
+* How will users know that they're still on your domain when they see your login page?
+* What do you need to do to provide additional browser security (e.g., implement Extended Validation)?
+* Where do you want to direct users in the event of errors?
+
+Auth0 provides tremendous flexibility when it comes to customizing and configuring Auth0 pages such as [Universal Login](#universal-login-and-login-pages) and [Password Reset](#password-reset-page-customization). So you can pretty much set up whatever UX look and feel you require. For many, the out-of-the-box experience - with perhaps a little alteration - is all that's required. However, for others the value of their brand and brand awareness requires more extensive customization. This flexibility extends to not only Auth0 pages, but via extensibility can also be applied to the [email templates](/architecture-scenarios/implementation/${platform}/${platform}-branding#email-template-customization). Auth0 [Custom Domain](/architecture-scenarios/implementation/${platform}/${platform}-branding#custom-domain-naming) functionality further enhances consumer awareness by providing users with the confidence and peace of mind when it comes to safety and security.
+
+<% if (platform === "b2b") { %>
+If you are sharing an Auth0 tenant across multiple customer organizations, providing each organization with their own domain of users and managing their credentials, you will need to consider how each user will know which credentials they should use and how they will trust that they are entering them somewhere safe and secure. See [Branding login by organization](#branding-login-by-organization) for details.
+<% } %>
+
+While Auth0 provides for default information when it comes to error situations, out-of-the-box information can be somewhat cryptic as the context that can only be provided by you is missing. Auth0 [error page customization](/architecture-scenarios/implementation/${platform}/${platform}-branding#error-page-customization) guidance can however help mitigate that by allowing you to provide information of a more context-specific nature via your own support organization.
+
+::: panel Best Practice
+To provide helpful resources for users who experience problems, you should also configure a friendly name and a logo, as well as provide the support email address and URL for your organization. To learn how, see [Dashboard Tenant Settings](/dashboard/reference/settings-tenant#settings).
+:::
+
+::: panel Get Started with Auth0 Videos
+Watch three short videos—[Brand: How It Works](/videos/get-started/07_01-brand-how-it-works), [Brand: Signup and Login Pages](/videos/get-started/07_02-brand-signup-login-pages), and [Brand: Emails and Error Pages](/videos/get-started/08-brand-emails-error-pages)—to learn how branding works with Auth0, how to use Auth0’s Universal Login feature to customize your sign up and login pages, and how to use Auth0 email templates and make changes to the reply email address, subject, redirect URL, and URL lifetime.
+:::
diff --git a/articles/architecture-scenarios/_includes/_branding/_password-reset.md b/articles/architecture-scenarios/_includes/_branding/_password-reset.md
new file mode 100644
index 0000000000..c3b0785c61
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_branding/_password-reset.md
@@ -0,0 +1,8 @@
+The [Password Reset](/universal-login/password-reset) page is used whenever a user takes advantage of password change functionality and, as with the login page, you can [customize it](/universal-login/password-reset#edit-the-password-reset-page) to reflect your organization's particular branding requirements.
+
+<% if (platform === "b2b") { %>
+If your organization users will all be isolated from each other (i.e, each organization gets its own Auth0 [database connection](/connections/database)), and you are branding the [Universal Login](#universal-login-and-login-pages) pages by organization, then it's also important to brand things like the [password reset](/universal-login/password-reset) page so users know for which organization the password change is occurring. This can be done in a couple of ways:
+
+* Create JavaScript on the Password Reset page that can pull resources from a CDN based on the connection parameter that indicates from which organization the user is coming.
+* Create a separate tenant for an organization and use Universal Login to customize what is required for that organization.
+<% } %>
diff --git a/articles/architecture-scenarios/_includes/_branding/_universal-login.md b/articles/architecture-scenarios/_includes/_branding/_universal-login.md
new file mode 100644
index 0000000000..69e2691da7
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_branding/_universal-login.md
@@ -0,0 +1,5 @@
+[Universal Login](/universal-login) is the recommended method for authenticating users, and it centers around use of the Login page. You can customize the Login page to support your organization's [branding requirements](/universal-login#customizing-universal-login).
+
+::: panel Best Practice
+If you choose to customize the Universal Login page script, we strongly recommend that you make use of version control. To do this, you should deploy the script to your Auth0 tenant via [deployment automation](/architecture-scenarios/implementation/${platform}/${platform}-deployment) or via one of the [alternative strategies](/universal-login/version-control).
+:::
diff --git a/articles/architecture-scenarios/_includes/_deployment/_introduction.md b/articles/architecture-scenarios/_includes/_deployment/_introduction.md
new file mode 100644
index 0000000000..c301f040e3
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_deployment/_introduction.md
@@ -0,0 +1,31 @@
+In addition to adopting best practices for change management and [QA](/architecture-scenarios/implementation/${platform}/${platform}-qa), successful customers will also integrate Auth0 collateral management as part of some automated deployment process. As discussed in the Architecture section under [SDLC support](/architecture-scenarios/implementation/${platform}/${platform}-architecture#sdlc-support), you will want to ensure you configure separate Auth0 tenants for development, testing, and production environments, and you will want that configuration to be almost identical for the tenant in each environment. Using deployment automation helps ensure this, so that each environment tenant is configured the same, and you will be less likely to see bugs show up as a result of mismatched configurations between environments.
+
+::: panel Best Practice
+However you configure deployment automation, we’d recommend you unit test your rules, custom DB scripts, and hooks prior to deployment, and run some integration tests against your tenant post-deployment too. For more details regarding this, see the [Quality Assurance](/architecture-scenarios/implementation/${platform}/${platform}-qa) guidance provided.
+:::
+
+Auth0 provides support for a couple of different options when it comes to the deployment automation approaches you can use, and each can be used in conjunction with the other if desired:
+
+* The [Auth0 Deploy CLI tooling](/extensions/deploy-cli) provides you with an easy-to-use script that can help you integrate with your existing Continuous Integration/Continuous Deployment (CI/CD) pipeline.
+* If you can’t integrate directly with, or for some reason you don’t have a CI/CD pipeline, then the Auth0 [Source Control Extensions](/extensions#deploy-hosted-pages-rules-and-database-connections-scripts-from-external-repositories) can provide an easy-to-set-up basic automation process with very low maintenance.
+
+::: warning
+Note that both the Deploy CLI Tool and source control extensions can cause destructive changes; manual changes made directly in the dashboard between automated deployments could be lost! For this reason, if either is used, then **all** changes should be deployed from the source control subsystem referenced via the tooling and not made manually.
+:::
+
+Each environment may also need some environment-specific configuration--Application Client ID’s and Client Secrets will be different between the Auth0 tenants, for example--so you’re going to want some way of being able to dynamically reference this rather than having hard-coded values. Auth0 provides support for handling environment-specific configuration information through one of the following two approaches:
+
+* Use [Tenant Specific Variables](#tenant-specific-variables)
+* Use [keyword replacement](extensions/deploy-cli/references/environment-variables-keyword-mappings) if using the Auth0 Deploy CLI tool
+
+## Tenant specific variables
+
+Auth0 allows you to configure variables that are available from within custom [extensibility](/topics/extensibility); these can be thought of as environment variables for your Auth0 tenant. Rather than hard code references that change when moving code between development, test, and production environments, you can use a variable name that is configured in the tenant and referenced by the custom extensibility code. This makes it easier for the same custom code to function, without changes, in different tenants as the code can reference variables which will be populated with tenant-specific values at execution time:
+
+* For use of variables in Rules, see how to [configure values](/rules/guides/configuration#configure-values)
+* For use of variables in Hooks, see how to configure [secrets](/hooks/secrets) in the editor
+* For use of variables in Custom DB Scripts, see the [configuration parameters](/connections/database/custom-db/create-db-connection#step-3-add-configuration-parameters)
+
+::: panel Best Practice
+It’s a recommended best practice to use variables to contain tenant-specific values as well as any sensitive secrets that should not be exposed in your custom code. If your custom code is deployed in GitHub/Gitlab/Bitbucket/VSTS, then using a tenant-specific variable avoids exposure of sensitive values via your repository.
+:::
diff --git a/articles/architecture-scenarios/_includes/_implementation-checklists.md b/articles/architecture-scenarios/_includes/_implementation-checklists.md
new file mode 100644
index 0000000000..c4624b459c
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_implementation-checklists.md
@@ -0,0 +1,13 @@
+Use the links below to download a spreadsheet that includes tasks for each phase of an Software Development Lifecycle (SDLC) project.
+
+Analyze Checklist
+
+Design Checklist
+
+Build Checklist
+
+Test Checklist
+
+Deploy Checklist
+
+Monitor Checklist
diff --git a/articles/architecture-scenarios/_includes/_keep-reading.md b/articles/architecture-scenarios/_includes/_keep-reading.md
new file mode 100644
index 0000000000..9697768911
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_keep-reading.md
@@ -0,0 +1,37 @@
+
+<% if (self !== "architecture") { %>
+* [Architecture](/architecture-scenarios/implementation/${platform}/${platform}-architecture)
+<% } %>
+<% if (self !== "provisioning") { %>
+* [Provisioning](/architecture-scenarios/implementation/${platform}/${platform}-provisioning)
+<% } %>
+<% if (self !== "authentication") { %>
+* [Authentication](/architecture-scenarios/implementation/${platform}/${platform}-authentication)
+<% } %>
+<% if (self !== "branding") { %>
+* [Branding](/architecture-scenarios/implementation/${platform}/${platform}-branding)
+<% } %>
+<% if (self !== "deployment") { %>
+* [Deployment Automation](/architecture-scenarios/implementation/${platform}/${platform}-deployment)
+<% } %>
+<% if (self !== "qa") { %>
+* [Quality Assurance](/architecture-scenarios/implementation/${platform}/${platform}-qa)
+<% } %>
+<% if (self !== "profile-mgmt") { %>
+* [Profile Management](/architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt)
+<% } %>
+<% if (self !== "authorization") { %>
+* [Authorization](/architecture-scenarios/implementation/${platform}/${platform}-authorization)
+<% } %>
+<% if (self !== "operations") { %>
+* [Operations](/architecture-scenarios/implementation/${platform}/${platform}-operations)
+<% } %>
+<% if (self !== "logout") { %>
+* [Logout](/architecture-scenarios/implementation/${platform}/${platform}-logout)
+<% } %>
+<% if (self !== "operations") { %>
+* [Operations](/architecture-scenarios/implementation/${platform}/${platform}-operations)
+<% } %>
+<% if (self !== "launch") { %>
+* [Launch Preparation](/architecture-scenarios/implementation/${platform}/${platform}-launch)
+<% } %>
diff --git a/articles/architecture-scenarios/_includes/_launch/_compliance.md b/articles/architecture-scenarios/_includes/_launch/_compliance.md
new file mode 100644
index 0000000000..8538d072c5
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_launch/_compliance.md
@@ -0,0 +1,37 @@
+There are several requirements related to privacy and compliance. Auth0 cannot provide legal guidance on your privacy or other regulatory obligations, but we can provide a curated list of privacy requirements below for which Auth0 offers features that may help you meet your obligations. Prior to launch, you should check that you’ve met all your privacy obligations and review the features outlined below to ensure you’re leveraging all the available Auth0 features to help you meet your privacy and compliance requirements.
+
+## Publish privacy policy and obtain user consent
+
+If you collect or process personal data about users, you should have published a privacy policy and have established procedures to ensure your operations abide by the contents of the policy. You also need to obtain a user’s consent for the collection and processing of information. Auth0 provides options for [displaying a link to your privacy policy storing user consent](/compliance/gdpr/features-aiding-compliance#conditions-for-consent).
+
+## Provide access to view, correct and erase data
+
+Privacy legislation often requires that users have the right to view and correct any data held about them. If you are a data controller, you should provide a mechanism for this. Auth0 customers can [build a self-service feature to access and correct data via the management API](/compliance/gdpr/features-aiding-compliance#right-to-access-correct-and-erase-data).
+
+## Provide access to data portability
+
+If you are a data controller, you may be obligated to provide users a means to export their data from your system in a transportable format. Auth0 provides [user data portability mechanisms](/compliance/gdpr/features-aiding-compliance#data-portability) to help you satisfy this obligation via both manual export capabilities and the Management API which enables you to implement a self-service feature for users.
+
+## Take steps to minimize personal data
+
+You should have reviewed the personal data you collect about users to ensure it is legitimately required for the purposes of the processing covered in the privacy policy and consent. You should also confirm you have [minimized the data you collect](/compliance/gdpr/features-aiding-compliance#data-minimization), and established a data retention policy. You can optionally elect to encrypt data you store in user metadata for additional protection.
+
+## Data retention policy enforcement automated
+
+You should have a published data retention policy and automate the enforcement of it. The Auth0 management API or the Auth0 dashboard can be used to facilitate [erasure of user accounts](/compliance/gdpr/features-aiding-compliance/right-to-access-data).
+
+## Protect personal data
+
+Regardless of whether you are a data controller or a data processor, you have obligations to protect the personal data you hold about users. This includes use of encryption where possible, and implementing reasonable security measures to protect user accounts. Prior to launch, you should check if you are using all the security features available from Auth0 to help with this such as Brute Force Detection, Multi-Factor Authentication (for both users and administrators), and a strong password policy if using passwords. You should also ensure you have a process ready to respond to [Brute Force attacks](/compliance/gdpr/features-aiding-compliance#protect-and-secure-user-data).
+
+## Supplier evaluation
+
+Another common compliance obligation is to perform due diligence review of the security of any third-party suppliers to which you expose personal data. For Auth0, you will find information to facilitate this task on the Auth0 [security and certifications](https://auth0.com/security/) page where you can view the security certifications Auth0 has obtained.
+
+## Additional resources
+
+Additional resurces that may be useful for your compliance requirements include:
+* [Auth0 Privacy Policy](https://auth0.com/privacy)
+* [Security and Compliance](https://auth0.com/security/)
+* [GDPR and Compliance Frameworks](/compliance)
+* [Auth0 support for customer requirements](/compliance/gdpr/features-aiding-compliance)
diff --git a/articles/architecture-scenarios/_includes/_launch/_introduction.md b/articles/architecture-scenarios/_includes/_launch/_introduction.md
new file mode 100644
index 0000000000..4909da3507
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_launch/_introduction.md
@@ -0,0 +1 @@
+Use this guide as you prepare for the launch of your application. We’ve included reminders about some content you may have viewed earlier during your planning or development phases as well as some new content unique to the launch phase. The sections below are useful to developers and project owners to ensure that you have everything lined up for a smooth launch. There are several things to check so it may help to assign ownership of different sections to different members of your team.
\ No newline at end of file
diff --git a/articles/architecture-scenarios/_includes/_launch/_launch.md b/articles/architecture-scenarios/_includes/_launch/_launch.md
new file mode 100644
index 0000000000..c0c5526d56
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_launch/_launch.md
@@ -0,0 +1,112 @@
+## Notifications / announcements
+
+It helps a launch go smoothly if all stakeholders are aware of the impending launch and understand the launch plan as well as their role and responsibilities. In addition to notifying teams that will be actively involved, it can help to notify teams that might be needed if anything goes wrong. Having someone on standby during a launch can help expedite response. Be sure to identify and notify any team that might need to answer questions from customers, including on social media.
+
+### Parties to notify
+
+* Customers
+* Business parters, if applicable
+* Application team(s) impacted by launch
+* Support teams
+* Network teams (network changes, on standby, in case of issues)
+* Security teams (on standby, in case of issues)
+* Marketing teams (ready for announcements, response to issues)
+* Social media teams (ready to monitor social media, respond)
+* Sales teams (prepared to answer questions from customers)
+* Customer success teams (prepared to answer questions from customers)
+
+## Notification plan
+
+Your notification plan should include elements such as the target audience, the key takeaways for the audience, the message content, the plans for distributing the notification and how to test the messaging.
+
+A list of elements to include in the plan are:
+
+* Target audience (consider both internal & external audiences)
+* Message
+* Timing
+* Dependencies
+* Responsible parties (who will send it)
+* Mechanism (how it will be communicated)
+* Test message and delivery (if applicable - test to ensure notifications sent)
+
+## Notification distribution
+
+A common tactic is to release notifications in batches to spread out the initial onslaught of load and reduce the scope of confusion if there are any unforeseen glitches. It’s easier to correct issues with a small group than during a big-bang launch.
+
+* One approach is to start with a relatively small batch of notifications, and if no issues are identified, increase the size of the batches over time.
+* You can also send out batches on a rolling schedule around the globe to spread out load hitting the system at once and have notifications arrive at an optimal time within each timezone to increase the likelihood of the messages being read.
+* You can do a soft-launch to a portion of users, such as individual customers, regions or some other grouping that makes sense for your application.
+
+## Outage windows (if needed)
+
+Some organizations require a formal request for an outage window if any outages or downtime is required for a launch. If your organization requires this, be sure to identify if any downtime is required for the cutover or launch (or other dependent systems) and file the necessary outage or change requests in advance of any lead-time requirements.
+
+## Cutover plan (if needed)
+
+Some launches involve cutover from a previous solution to a new solution. If your project fits this scenario, you should be sure to identify everything that needs to happen as well as any dependencies, the responsible party for each task, and necessary timing. You may wish to plan alternates for all important roles or in each region in case anyone is unexpectedly sick or otherwise unavailable. A checklist of items to consider for the cutover plan is:
+
+* Have you documented the cutover plan and rollback plan if needed?
+* Are backups needed of anything prior to change?
+* Are any preparatory data changes required?
+* Any DNS records to be changed?
+* Any Firewall changes?
+* Any new monitoring targets?
+* Any software to be deployed?
+
+## Go / no-go criteria
+
+In your overall launch plan, it is helpful to have go/no-go criteria and to have discussed in advance the types of issues which could occur and which could be worked through vs would require reverting. A launch plan can specify periodic check-in timeframes with criteria of what to assess at each checkpoint and how long to allow an issue to continue unresolved.
+
+For each stage of the launch, it helps to have success criteria defined, that indicate the launch is proceeding as planned and can continue. Some example criteria could be:
+
+* User signups growing with minimal errors
+* User logins at expected rate, minimal errors
+* Reported support issues below a certain threshold
+* No issues identified that could lead to corrupted data
+
+It’s also helpful to have identified criteria which could trigger a “no-go” decision to halt the launch. The risk tolerance for each environment varies, but a few example criteria might include:
+
+* High percent of user signup or login resulting in errors that cannot be resolved quickly
+* High number of support issues that cannot be resolved quickly
+* Condition identified that could lead to data corruption
+* High severity security issue discovered
+
+## Rollback
+
+It is always wise to have a plan for how to rollback or revert a launch, just in case something unforeseeable occurs which cannot be resolved. Reviewing the launch plan for every step which involves a change can help identify the tasks or changes requires to revert a launch or cutover.
+
+The rollback plan should include the steps to take, the sequence, how long each is likely to take and the responsible party. Understanding the cumulative time required to roll back can help to determine the timing of the final go/no-go decision to fit within any required outage window.
+
+If any data is migrated or changed for the launch, the plan should include how to revert it, if needed. Reverting may require running scripts to undo operational changes or restoring a data store from a backup taken before the launch process began.
+
+It is also necessary to plan for the case where some data is entered into a new system before it has to be reverted. Will such data / transactions need to be abandoned with the rollback or will you have a way to capture and apply them elsewhere so they aren’t lost?
+
+If the resolution of issues or process to revert could potentially take longer than one shift, you’ll want to ensure you have a primary and perhaps a secondary person available and prepared to handle things during each work shift. If an issue results in the need for prolonged response, significantly beyond one shift, there are limits for how long people can realistically function without a break. It can help to be prepared with resources for a follow-the-sun issue response effort if needed.
+
+## Standby contacts
+
+As the launch day approaches, it’s a good idea to identify all contacts who might be needed for troubleshooting or resolving issues and request them to be on standby and ready to help if needed. The launch leader should have contact information for each person on the standby list to expedite communications.
+
+If there is a physical or virtual "launch room", the people on standby should know where it is and be ready to join if needed. Having a central room or video conference prepared can expedite communications and troubleshooting across all parties if an issue occurs.
+
+## Success Criteria
+
+A lot of planning goes into a launch in order to be successful, but will you know how to evaluate the launch? If you define success criteria before the launch, you can determine what to monitor and if any additional monitoring or checks need to be in place to evaluate the launch.
+For example - if one element of the success criteria is the number of sign-ups or logins - do you have a way of monitoring that and has it been tested to ensure it is accurate?
+
+You’ll want statistics to be able to trumpet the success of your launch. You don’t want to find out after the launch that you didn’t capture any data to quantify all the hard work your team put into the launch.
+
+## Risks & mitigations plan
+
+It’s no fun to think of things that could go wrong, but if anything happens, you’ll be glad you did as having a plan can expedite response. A few examples to plan for include:
+
+* Software application bug
+* Application incompatibility with user browser settings
+* Network failure/outage
+* DoS attack
+* Hosting environment failure
+* Load / capacity issues
+* Data / corruption issues
+* Security vulnerability discovered
+
+If you had a beta period, it may help to review the results of the beta to identify additional possible failure scenarios.
diff --git a/articles/architecture-scenarios/_includes/_launch/_operations.md b/articles/architecture-scenarios/_includes/_launch/_operations.md
new file mode 100644
index 0000000000..22a43ad85d
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_launch/_operations.md
@@ -0,0 +1,96 @@
+## Status
+
+You should ensure your operations staff knows how to monitor Auth0 service status and has set up a means to subscribe to updates on Auth0 status.
+
+<%= include('../../_includes/_operations/_service-status.md', { platform: 'b2b' }) %>
+
+## Email provider setup
+
+You should double check that you have set up your own email provider to support production volumes of emails that might be sent to customers for signup, email validation, account recovery and the like.
+
+<%= include('../../_includes/_operations/_email-provider.md', { platform: 'b2b' }) %>
+
+## Infrastructure
+
+<%= include('../../_includes/_operations/_infrastructure.md', { platform: 'b2b' }) %>
+
+## NTP
+
+If this is not handled automatically by your hosting environment, you should have scripts which will automatically restart NTP (Network Time Protocol) if it fails and alerts that will notify someone if NTP is not running. Authentication transactions rely on accurate system time because security tokens may be evaluated as expired when received if there are time discrepancies between sending and receiving systems.
+
+## LoadBalancer timeouts checked
+
+If you use the AD/LDAP connector, you should check the load balancer settings in your environment to see if they terminate long running connections that are inactive. If they do, you can modify the [Auth0 AD/LDAP Connection settings](/connector/modify#configuration-file) to use the `LDAP_HEARTBEAT_SECONDS` setting to send periodic heartbeat messages to keep the connection open.
+
+## LoadBalancer configuration
+
+If your application maintains server state such that it depends on sticky load balancing to route users to a particular server, it can be beneficial to double check that all load balancer configurations are correct. One load balancer in a pool that is out of sync can cause intermittent errors that are hard to troubleshoot. A quick check of load balancer configuration can avoid such issues in the first place.
+
+## Logs
+
+You should check that you have set up the ability to capture log data, that logs are covered by your data retention policy and you have mechanisms to enforce logs data retention limits. You should also make sure that your development, support, and security teams know how to access logs data for troubleshooting and forensics purposes. Exporting log files to services that provide comprehensive analytics can help you identify patterns such as usage trends and errors.
+
+<%= include('../../_includes/_operations/_logging.md', { platform: 'b2b' }) %>
+
+## Monitoring
+
+Be sure to set up proactive monitoring of the Auth0 service as well as end-to-end authentication through your application.
+
+<%= include('../../_includes/_operations/_monitoring.md', { platform: 'b2b' }) %>
+
+## Auth0 Notifications
+
+You should ensure your team is monitoring all of the following communication channels from Auth0 to stay abreast of important announcements and changes.
+
+<%= include('../../_includes/_operations/_notifications.md', { platform: 'b2b' }) %>
+
+In addition, you should periodically check the [Auth0 migrations page](/product-lifecycle/migrations) for news about upcoming deprecations that might require your team to make changes.
+
+## Automated Deployment, version control
+
+While not required, it is highly recommended that you have deployment automation set up. You can respond more efficiently if you need to make any changes after launch if you have automated the ability to deploy and revert changes to dev, test and production environments.
+
+<%= include('../../_includes/_deployment/_introduction.md', { platform: 'b2b' }) %>
+
+## Backup / Restore
+
+You should have a plan and mechanism in place to support any backup/restore capability needed for your project. This can be done using the Auth0 Management API for data as well as the Automated Deployment capabilities described in the automated deployment section for Auth0 configuration.
+
+As noted in the Auth0 [Data Tenant Restore policy](policies/restore-deleted-tenant) and [Data Transfer policy](policies/data-transfer), Auth0 does not restore deleted tenants or move data between tenants. Auth0 provides the Auth0 Management API to provide customers a completely flexible capability to backup, restore and move data as needed. Customers can write scripts to retrieve data from Auth0 for backup purposes, and similarly write scripts for use with the Automated Deployment capability to restore any aspect of their Auth0 configuration.
+
+## Versions Up to Date
+
+You should double check that all technologies in your application stack, as well as browser versions used by your users are on current, up-to-date versions as this will impact Auth0’s ability to provide support if issues arise.
+* Check you are using the latest supported version of node.js in [Auth0 dashboard settings](/dashboard/dashboard-tenant-settings#extensibility).
+* Check you are using a version of SDK/Libraries supported by Auth0 per the [Auth0 Support Matrix](/support/matrix).
+
+## Certificate rollover plan
+
+Certificates may be used in identity deployments. To ensure a certificate expiration does not catch you by surprise, you should have a list of certificates in your environment along with the expiration dates, how you will be notified when expiration draws near and how the certificate rollover process works.
+
+### SAML connections
+
+For SAML connections, you obtain a certificate from the IdP and upload it to a SAML connection for the IdP in your Auth0 dashboard. When one of these certificates is about to expire, Auth0 will send email to dashboard administrators warning of the upcoming expiration. You can obtain the new certificate and upload it using the connection configuration screen.
+
+### WS-Fed connections
+
+For WS-Fed connections, if you configure them by specifying an ADFS URL, any changes will be picked up by a daily update. You can trigger an update manually by visiting the connection configuration page in the Auth0 dashboard and doing a Save. If a certificate is changed at the remote IdP, Auth0 can be updated by those mechanisms or by uploading a new metadata file in the same connection configuration screen.
+
+## Disaster Recovery / Business Continuity Plan in place
+
+While not an absolute requirement prior to launch, it is useful to have a disaster recovery plan in place to ensure business continuity in the face of different types of disasters, including system outages and natural disasters hitting a region where critical staff is located.
+
+## Processes documented
+
+Another item which is not an absolute requirement, but also recommended is to ensure all processes related to Auth0 are documented. This can include the following:
+
+* Change management for configuration
+* Deployment of new changes and any automatic deployment mechanisms used, how to revert to previous version if issues found
+* Certificate rollover processes, if any
+* Adding or removing new Identity Providers, if applicable
+* Changes to user profile structure in Auth0 or in directories Auth0 pulls from
+* Adding or removing applications or APIs
+* Capturing and exporting logs
+* Backup/restore process you have implemented
+* User management (forgotten password, lost phone)
+* Root cause analysis after an incident
diff --git a/articles/architecture-scenarios/_includes/_launch/_support.md b/articles/architecture-scenarios/_includes/_launch/_support.md
new file mode 100644
index 0000000000..3eea47b43a
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_launch/_support.md
@@ -0,0 +1,61 @@
+## Review Auth0 Policies
+
+When starting to prepare for your launch, be sure to read through [Auth0 Policies](/policies) and prepare your production operations accordingly for any required lead times or responsibilities on your part, according to the policies.
+
+## Review your Support plan, SLAs, Severity definitions and Support center documentation
+
+You should review the specifics of the [support plan](/support#support-center) you’ve purchased and the [Service Level Agreements](/support#defect-responses) associated with it, to ensure it is adequate for your needs. If you haven’t already done so, explore the [support center](https://support.auth0.com/) and familiarize yourself with support features such as viewing suggested solutions to common issues and [filing tickets](/support/tickets) and viewing your quota usage. It will be helpful to review the [severity level definitions](/support#defect-resolution-procedures) for support tickets so that you file tickets with the correct severity. One important note is that it is not possible today in the Support Center to increase the severity of a support ticket. If you file a ticket for a medium-grade issue which later becomes a high severity issue, you should file a new urgent, high severity ticket that explains anything new that triggers the urgency and references the original ticket for details.
+
+You should also ensure your development and support teams are familiar with the [Auth0 community forum](https://community.auth0.com/), discussed further below. Customers can often find answers there right away to common issues, avoiding the need to file a ticket, so it should be your first stop for technical questions.
+
+## Review the Auth0 community forum
+
+The [Auth0 community forum](https://community.auth0.com/) contains a wealth of information. If you have a question, chances are someone else has already asked the question on the forum. Answers are contributed by both Auth0 staff and the larger community of Auth0 users.
+
+Important notices are posted to the community forum to help you stay abreast of important news. Be sure to check out the “Community” and “FAQ” categories. The Community category contains pro-active posts on product announcements, roadmap information, How-To videos as well as important information about any upcoming feature deprecations.
+
+It’s a good idea to check out the Auth0 Community on a regular basis, not just when you have questions. While you are there, if you see a question you’ve already solved, please contribute your wisdom to help others!
+
+## Gather Auth0 troubleshooting information needed for support tickets
+
+We recommend your support team become familiar with our [troubleshooting guides](/troubleshoot) specific to identity protocols and Auth0. This includes the questions to research and information to collect before posting a question on the Auth0 forum or filing a support ticket. Authentication transactions often span multiple systems so there are some specialized troubleshooting techniques that are helpful to learn.
+
+## Have troubleshooting tools ready
+
+Your team will doubtless have already done some troubleshooting during the development of your application, but we recommend making sure your support team is also familiar with any tools below relevant to your project. If you need to file a ticket, the Auth0 support team may ask for a HAR (HTTP Archive) file to help analyze the issue so it’s helpful for your support staff to be familiar with how to do this.
+
+### Capture HAR file
+
+A [HAR file](/troubleshoot/guides/generate-har-files) captures a sequence of browser interactions and is a commonly used tool when debugging authentication issues. The process of authenticating a user often involves redirecting the user’s browser from an application to Auth0, and possibly to another remote Identity Provider, depending on the type of connection used. You can capture the redirection and the responses and analyze it to find clues about the cause of an issue.
+
+### Analyze HAR file
+
+Analyze the [HAR file](/troubleshoot/guides/generate-har-files#analyze-har-files) to obtain valuable troubleshooting information. It shows the sequence of browser redirects involved in an authentication transaction, along with the parameters used. The HAR file also shows if the authentication process stopped mid-stream and if so where, which helps to pinpoint the location of the issue. The HAR file contains tokens returned to the application front-end, and these can be pasted into appropriate viewers to see if they contain the expected contents.
+
+### View JWT
+
+The [jwt.io](https://jwt.io) tool was written by Auth0 and allows you to view the contents of a JWT-formatted token. Applications that delegate authentication to Auth0 via OIDC will receive an ID Token from Auth0. Depending on your type of application, the ID Token may be captured in a HAR file. The ID Token is in JWT format and can be pasted into jwt.io to view the contents of the ID Token.
+
+### View SAML request/response
+
+There are many SAML decoders available. The [samltool.io](https://samltool.io) decoder was written by Auth0 and allows you to view the contents of a SAML Request or Response. Applications that delegate authentication to Auth0 via SAML or use a SAML type of connection in Auth0 will use SAML Requests and Responses. These SAML Requests and Responses may be captured in a HAR file. The requests and responses can be pasted into samltool.io or other SAML decoders to view the contents of the SAML Request or Response.
+
+## Review Auth0 support matrix
+
+One potential cause of issues is using out of date versions of SDKs or libraries. We strongly recommend your team check your software stack, browsers, SDKs and libraries against the [Auth0 support matrix](/support/matrix) to ensure you are running on up-to-date, supported versions. In the event of an issue, the Auth0 support team may ask you to upgrade to a supported version. To avoid slowing down progress on issue resolution, be sure you are on up-to-date versions.
+
+## Use Auth0 feedback portal
+
+Auth0 welcomes feedback and ideas from Auth0 customers. If you have a suggestion for our product team, you can submit product feedback directly on the [Product Feedback portal](https://auth0.com/feedback).
+
+## Prepare real-time webtask log extension
+
+For debugging and supporting custom code in Auth0, including Rules, Hooks, Custom DB Scripts, and Custom OAuth Connections, knowledge of the [Realtime Webtask Log](/extensions/realtime-webtask-logs) is essential. This enables you to view output from your custom code, including output from console.log statements.
+
+::: panel Best Practice
+We recommend installing the real-time webtask log extension and getting familiar with using it to view log output from your custom code as a debugging and support tool.
+:::
+
+## Troubleshooting
+
+You should prepare to [troubleshoot issues](/troubleshoot/basics) both during your development as well as after your application or API goes live. Make sure your development and support teams are prepared with knowledge of troubleshooting tools, and the list of common issues to check when troubleshooting an issue.
diff --git a/articles/architecture-scenarios/_includes/_launch/_tenant-check.md b/articles/architecture-scenarios/_includes/_launch/_tenant-check.md
new file mode 100644
index 0000000000..2f9f2ce0d5
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_launch/_tenant-check.md
@@ -0,0 +1,112 @@
+## Tenant Check
+
+This section covers a list of configurations to check in your tenant. This should be done periodically during development and sufficiently before launch so you have time to fix anything amiss.
+
+### General tenant check
+
+#### Tenant preparation check
+
+Check to ensure you have [set up tenant environments](/dev-lifecycle/setting-up-env) to support your SDLC lifecycle and that Dev, Test and Prod tenants are cleanly separated so that ongoing development work after launch doesn’t negatively impact your production environment.
+
+<%= include('../../_includes/_architecture/_sdlc-support.md', { platform: 'b2c' }) %>
+
+#### Tenant association check
+
+<%= include('../../_includes/_architecture/_tenant-association.md', { platform: 'b2c' }) %>
+
+#### Specify production tenant
+
+To ensure Auth0 recognizes your production tenant, be sure to [set your production tenant](/dev-lifecycle/setting-up-env#set-the-environment
+) with the “production” flag in the Support Center.
+
+#### Tenant production Check
+
+Auth0 provides a [Production Check](/pre-deployment) facility to detect many common errors. You should ensure this has been run and any findings from the report mitigated before launch.
+
+In addition, you should check the [best practice configurations advice](/pre-deployment/tests/best-practice), for which checking cannot be automated.
+
+#### Tenant Settings Check
+
+##### Tenant Settings
+
+Make sure to follow the [Auth0 tenant settings best practices](/best-practices/tenant-settings#set-up-branding-configuration) in configuring your logo as well as your support email and support URL so user's know how to get help if an issue occurs. You'll want to check your SSO Session Timeout settings and the list of dashboard admins with access to your production tenant as well. For further information on tenant setting, see the Auth0 dashboard [tenant settings documentation](/dashboard/dashboard-tenant-settings#settings).
+
+##### Error Page Customization
+
+<%= include('../../_includes/_branding/_error-page.md', { platform: 'b2c' }) %>
+
+##### Legacy feature flags off
+
+If you have an older tenant, you may have various legacy feature flags enabled in your [tenant settings advanced tab](/dashboard/dashboard-tenant-settings#advanced). If you have any toggles on in the “Migrations” section of this tab, you should review your usage and make plans to migrate off the legacy feature.
+
+##### Delegated admin extension
+
+While you are checking the list of users with access to your production tenant, don't forget to check any users specified in the [Delegated Admin Extension](/extensions/delegated-admin/v3).
+
+#### Custom Domain Naming set up
+
+<%= include('../../_includes/_branding/_custom-domain-naming.md', { platform: 'b2c' }) %>
+
+### Application and Connection settings check
+
+Each of your application configurations in Auth0 should be checked against the [application configuration best practices](/best-practices/application-settings).
+
+Each of your connection settings should be reviewed against the [connection configuration best practices](/best-practices/connection-settings).
+
+In addition, you should review that all connections are appropriate and that no experimental connections are left in your production tenant as they could enable unauthorized access.
+
+If you use SAML connections, it is a best practice to configure the connections to sign SAML requests.
+
+### Page customization check
+
+If you use the Auth0 universal login page, password reset page, or Guardian multi-factor authentication, you should check that you have adequately customized the pages displayed to the end user.
+
+#### Universal Login Page
+
+<%= include('../../_includes/_branding/_universal-login.md', { platform: 'b2c' }) %>
+
+#### Password Reset Page customization
+
+<%= include('../../_includes/_branding/_password-reset.md', { platform: 'b2c' }) %>
+
+#### Guardian
+
+<%= include('../../_includes/_branding/_guardian.md', { platform: 'b2c' }) %>
+
+### Authorization check
+
+If you are using Auth0’s [authorization feature](https://auth0.com/docs/authorization), be sure to double check all privileges granted to ensure authorizations are appropriate for your production environment.
+
+### API configuration check
+
+#### Access token expiration
+
+You should double check the [API access token expiration settings](/dashboard/reference/settings-api) to ensure they are appropriate for each API in your production environment.
+
+#### API offline access
+
+If your application does not request refresh tokens, this should be off.
+
+#### Access token signing algorithm
+
+It is recommended that the [API access token signing algorithm](/getting-started/set-up-api#signing-algorithms) be set to RS256 rather than HS256 to minimize exposure of the signing key.
+
+#### API Access token validation
+
+If you have any custom APIs, be sure to check that they are adequately [validating the access tokens](/api-auth/tutorials/verify-access-token) they receive before using the information in them.
+
+### API Scopes
+
+If you have applications making machine-to-machine calls to any of your APIs, you should review the scopes specified for the API to ensure they are all appropriate for your production environment. For further information see the documentation on [client credentials grant](/api-auth/config/using-the-auth0-dashboard).
+
+### Rules/Hooks check
+
+You should also have aligned your rules with Auth0 [rules best practices](/best-practices/rules).
+
+### Email templates customized
+
+<%= include('../../_includes/_branding/_email-templates.md', { platform: 'b2b' }) %>
+
+### Attack protection configured
+
+<%= include('../../_includes/_authentication/_attack-protection.md', { platform: 'b2b' }) %>
diff --git a/articles/architecture-scenarios/_includes/_launch/_testing.md b/articles/architecture-scenarios/_includes/_launch/_testing.md
new file mode 100644
index 0000000000..7ceb804ac1
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_launch/_testing.md
@@ -0,0 +1,25 @@
+Prior to launch, you should have completed all the testing that applies to your environment.
+
+<%= include('../../_includes/_qa/_introduction.md', { platform: 'b2c' }) %>
+
+### Unit testing
+
+<%= include('../../_includes/_qa/_unit-testing.md', { platform: 'b2c' }) %>
+
+### Integration testing
+
+<%= include('../../_includes/_qa/_integration-testing.md', { platform: 'b2c' }) %>
+
+### Mock Testing
+
+<%= include('../../_includes/_qa/_mock-testing.md', { platform: 'b2c' }) %>
+
+### Pen testing (optional)
+
+If you will be conducting penetration tests, you should be aware of Auth0’s [penetration testing policy](/policies/penetration-testing) and abide by it. Penetration tests require advance notice to Auth0 so that your tests are not mistaken for malicious activity and shut down.
+
+### Load testing (optional)
+
+If you will be conducting load tests, you should be aware of Auth0’s [load testing policy](/policies/load-testing) and abide by it. Load tests require advance notice to Auth0. In planning your load testing, you will also need to be aware of Auth0’s [API rate limits](/policies/rate-limits).
+
+<%= include('../../_includes/_qa/_load-testing.md', { platform: 'b2c' }) %>
diff --git a/articles/architecture-scenarios/_includes/_logout/_introduction.md b/articles/architecture-scenarios/_includes/_logout/_introduction.md
new file mode 100644
index 0000000000..08510e5ea8
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_logout/_introduction.md
@@ -0,0 +1,47 @@
+[Logout](/logout) is the act of terminating an authenticated session when it's no longer needed, thus minimizing the likelihood that unauthorized parties can "take over" the session. This is typically achieved by provisioning a logout option on the user interface you provide to your users. Multiple types of sessions can be created when a user logs in (e.g., local application sessions, Auth0 session, third-party Identity Provider sessions), and you will need to determine which of these sessions need to be terminated when the user clicks any **Logout** option.
+
+::: panel Best Practice
+Your logout behavior should make it clear to a user which session(s) are being terminated, and ideally, will display a visual confirmation of logout afterward.
+:::
+
+When configuring logout behavior, you'll need to consider:
+
+* Which sessions should be terminated when the user initiates logout?
+* What information should you provide to users as confirmation of the sessions terminated?
+* Where should users be redirected to after logout completes?
+* How long do you want sessions to last in the event that users do not trigger the logout process?
+<% if (platform === "b2b") { %>
+* Should the End User be logged out of all of their application sessions when they log out of one?
+* Should the session with an organization's IDP also be terminated at logout?
+<% } %>
+
+Given the varying types of sessions that can be created whenever a user logs in, there are several types of logout possible. Local application logout ends the session with the application, whereas Auth0 logout [terminates the Auth0 session](/logout/guides/logout-auth0). If you have organizations that are using their own IDP, you may want to consider a [Federated Logout](#federated-logout) strategy and implement accordingly. Global, or [Single Logout](/logout/guides/logout-applications) (SLO), ends the Auth0 session and also sends a logout request/notice to applications relying on the Auth0 session.
+
+The functionality provided by your application, as well as your use of features like [Single Sign-on (SSO)](/sso), will inform your decision as to what type of logout is required and what visual confirmation you'll need to provide to your users. Regardless of which option you choose, the logout process you implement should make it clear to the user which sessions are being terminated, and also when the logout process has completed.
+
+::: warning
+If the logout feature in one application terminates an Auth0 SSO session that is used by other applications, the user may lose work if they have uncommitted transactions. Be sure to add the functionality needed to handle such conditions to minimize the likelihood of lost work.
+:::
+
+<% if (platform === "b2b") { %>
+In some situations, a user may be expected to logout of all associated applications when they log out of any one of the applications you provide. This is something that can add complexity. However if you have concerns that users could leave themselves vulnerable (perhaps due to data sensitivity or the like), then you will likely need to review [Single Logout](#single-logout) and implement accordingly.
+
+<% } %>
+
+## Where to send users after logout
+
+Once your user logs out, they will be redirected to a specific location of your choosing. This location is specified as the **logout redirect URL**, and you can [define this as a parameter](/logout/guides/redirect-users-after-logout) via the Auth0 Dashboard.
+
+The URL(s) you use to redirect users after logging out must be [whitelisted in the Dashboard](/logout#redirect-users-after-logout) to mitigate open-redirect security vulnerabilities. You can whitelist them at the tenant or application levels.
+
+::: note
+If the user logs out and you redirect them back to the application, and the application redirects to an Identity Provider that still has a valid session for the user, the user will be logged in silently to the application. This may appear to the user as if the logout process didn't function properly.
+:::
+
+## Automatic termination of sessions
+
+Not all users will trigger the logout process manually, so Auth0 also provides **session timeout** to prevent overly long-lived sessions. This setting is [available and configurable via the Auth0 Dashboard](/dashboard/reference/settings-tenant#login-session-management).
+
+::: panel Get Started with Auth0 Video
+Watch this short video [Logout](/videos/get-started/10-logout) to learn about different kinds of logout behavior and different session layers. Learn how to configure callback URLs in the application and tenant settings in the Dashboard.
+:::
diff --git a/articles/architecture-scenarios/_includes/_multitenancy.md b/articles/architecture-scenarios/_includes/_multitenancy.md
new file mode 100644
index 0000000000..50c06de00b
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_multitenancy.md
@@ -0,0 +1,3 @@
+Many B2B platforms implement some form of isolation and/or branding for their customers' organization, and this can add complexity to any Identity and Access Management (IAM) system. If this applies to you, then we recommend you take some time to read through our guidance and best practice advice concerning this type of environment.
+
+Multiple Organization Architecture (Multitenancy) Overview
diff --git a/articles/architecture-scenarios/_includes/_operations/_email-provider.md b/articles/architecture-scenarios/_includes/_operations/_email-provider.md
new file mode 100644
index 0000000000..8f83e0bece
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_operations/_email-provider.md
@@ -0,0 +1,5 @@
+Auth0 sends [emails](/email) to users for events such as signup welcome, email validation, breached password, and password reset events. You can customize the email templates for each type of event, and advanced customization of email handling is also possible. Auth0 provides a test email provider with limited capacity for basic testing, but you must set up your own email provider for production use, and customization of email templates will not work until you have established your own provider.
+
+::: panel Best Practice
+The default Auth0 email provider does not support sending production volumes of email or customization of email templates. You should therefore configure your own email provider before deploying to production.
+:::
diff --git a/articles/architecture-scenarios/_includes/_operations/_infrastructure.md b/articles/architecture-scenarios/_includes/_operations/_infrastructure.md
new file mode 100644
index 0000000000..540e16cd72
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_operations/_infrastructure.md
@@ -0,0 +1,3 @@
+### Firewalls
+
+If custom code executing in Auth0 (such as in a Rule, Hook, or Custom DB scripts) will call a service inside your network, or if you configure an on-premise SMTP provider in Auth0, then you may need to configure your firewall to allow [inbound traffic from Auth0](/guides/ip-whitelist#inbound-calls). The IP addresses to allow through the firewall are specific to each region and are listed on the Rules, Hooks, Custom DB scripts, and email provider configuration screens in your Auth0 dashboard (as described in [Whitelist IP Addresses](/guides/ip-whitelist)).
diff --git a/articles/architecture-scenarios/_includes/_operations/_introduction.md b/articles/architecture-scenarios/_includes/_operations/_introduction.md
new file mode 100644
index 0000000000..33fb73bae3
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_operations/_introduction.md
@@ -0,0 +1,29 @@
+Operationalization requires configuring or setting up infrastructure to support the scalable, measurable, and quantifiable operation that’s necessary for business continuity. In Auth0, this includes configuring supporting services (such as email providers), monitoring services for your deployment, detecting anomalous situations, and making preparations to recover quickly and smoothly when something goes wrong in a production environment.
+
+Establishing effective operational behaviors is something that successful customers have found pays dividends, and there are a number of things you will want to consider when looking at your workflow:
+
+* What should you do to proactively detect failures?
+* How can you obtain data on Auth0’s operational status?
+* What should you do about Auth0 security bulletins related to the Auth0 service?
+* Does Auth0 provide information regarding impending changes in the Auth0 service?
+* How can you check for important notices from Auth0?
+* What should you do with Auth0 log data so that you can analyze it and keep it for longer than Auth0’s limited data retention period?
+* How can you scan Auth0 logs to determine if peak loads in your application trigger any rate limits or other errors?
+* What email services should you use to support production volumes of email messages to users? Can I use Auth0's out-of-box email provider in my production environment?
+* Do you need to configure your firewall and what firewall ports will you need to open for internal services that need to receive communications from Auth0 (such as custom databases, web services, and email servers)?
+<% if (platform === "b2b") { %>
+* How will you provision new organizations?
+* Do you need to provide self-service provisioning for your customer so that they can configure their own organizational IdPs?
+<% } %>
+
+Auth0 supports functionality for [monitoring](#monitoring) Auth0 service operation as well as providing information regarding Auth0 [service status](#service-status). In addition, Auth0 makes security-related bulletins as well as information regarding upcoming changes to the Auth0 service available via various [notifications](#notifications). Auth0 [logging](#logging) services also provide extensive functionality for tracing and identifying operational anomalies, including restrictions encountered due to rate limiting and/or excessive loading.
+
+Out-of-box, Auth0 provides email delivery services to help you accelerate your integration. These services, however, are not meant for scale-of-use in production environments, and do not provide for any specific service level or guarantee when it comes to email delivery. Our best practice recommendation, which customers typically follow, involves configuring your own [email service provider](#email-provider-setup).
+
+You may also need to make changes to [infrastructure](#infrastructure) configuration in order to support integration with Auth0 and to support use of Auth0 extensibility. For example, if you need to provide callbacks to your internal or even external infrastructure (e.g., if you need to make external API calls in Rules or Hooks, or via custom database scripts if you need to leverage existing legacy identity storage), then you may need to configure your Firewall settings.
+
+<% if (platform === "b2b") { %>
+Once you know how you want organizations to be represented in your system, you will want too consider how you are going to provision the organization itself. See [Provisioning organizations](#provisioning-organizations) for more information.
+
+In addition, many of our customers have developed one or more self-service portals for use by their customers' organization admins to provide self-service capabilities for configuring their own [IdPs](#self-service-idp-provisioning).
+<% } %>
diff --git a/articles/architecture-scenarios/_includes/_operations/_logging.md b/articles/architecture-scenarios/_includes/_operations/_logging.md
new file mode 100644
index 0000000000..41ce91d599
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_operations/_logging.md
@@ -0,0 +1,15 @@
+Auth0 provides extensive capability when it comes to the logging of events, and also in the scanning of logs in order to identify event anomalies (see [logs documentation](/logs) for further details). Standard log retention period for Auth0 logs is determined by subscription level with the shortest period being 2 days and the longest period being only 30 days. Leveraging Auth0 support for integrating with external logging services will allow you to retain logs outside of this, and will also provide for log aggregation across your organization.
+
+::: panel Best Practice
+You should leverage one of the Auth0 logs extensions to send log data to an external log analytics service. This will enable keeping data for longer periods of time and provide advanced analytics on the log data.
+:::
+
+You should review the log data [retention period](/logs/references/log-data-retention) for your subscription level, and implement a log data export extension to send log data to an external log analytics service. Development teams can use log files for troubleshooting and detecting intermittent errors that may be hard to find via QA tests. Security teams will probably want log data in case forensic data is ever needed. Exporting log files to services that provide comprehensive analytics can help you see patterns such as usage trends and attack protection triggers.
+
+### Rate limits and other errors
+
+Auth0 provides a unique error code for errors reported when the [rate limit is exceeded](/policies/rate-limits#exceeding-the-rate-limit). You should set up automatic scanning of logs to check for rate limit errors so you can proactively address activity that hits rate limits before it causes too much trouble for your users. Auth0 also publishes error codes for other types of errors, and you will find it helpful to scan logs for [authentication errors](/libraries/error-messages) as well as errors from Auth0 Management API calls (Management API error codes are shown below each call in the [Management API Explorer](/api/management/v2)).
+
+::: panel Best Practice
+Calling the Management API to retrieve user profile information from within a Rule is a common cause of rate limit errors because such API calls can execute for every login as well as periodic session checks.
+:::
diff --git a/articles/architecture-scenarios/_includes/_operations/_monitoring.md b/articles/architecture-scenarios/_includes/_operations/_monitoring.md
new file mode 100644
index 0000000000..d64277752e
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_operations/_monitoring.md
@@ -0,0 +1,5 @@
+You should establish mechanisms for [monitoring Auth0 implementations](/monitoring), so your support or operations team receives the timely information needed to proactively handle service outages. Auth0 provides monitoring endpoints that can be incorporated into your monitoring infrastructure. These endpoints are designed to provide a response suitable for consumption by monitoring services. It should be noted that they only provide data on Auth0. For complete end-to-end monitoring, which is essential for checking the ability of users to log in, we recommend that you set up synthetic transaction monitoring. This will provide greater granularity for your monitoring and enable you to detect outages unrelated to Auth0 as well as degradation of performance, so you can respond more proactively.
+
+::: panel Best Practice
+You should set up the ability to send synthetic login transactions to facilitate end-to-end monitoring of authentication. You can do this with a simple application that uses the [Resource Owner Password Grant](/api-auth/tutorials/password-grant) in combination with a test user that has no privileges, and don’t forget about [Auth0 rate limiting policies](/policies/rate-limits) too.
+:::
diff --git a/articles/architecture-scenarios/_includes/_operations/_notifications.md b/articles/architecture-scenarios/_includes/_operations/_notifications.md
new file mode 100644
index 0000000000..57dd93c1f9
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_operations/_notifications.md
@@ -0,0 +1,21 @@
+There are several different types of notifications from Auth0 that you should watch for as they contain important information that could impact your tenant(s) and project.
+
+::: note
+Proactive security notifications and other operational announcements are sent by Auth0 to dashboard administrators. You should ensure that the people who need to receive such messages are dashboard administrators.
+:::
+
+### Dashboard notifications
+
+From time to time, Auth0 may send an important announcement related to your tenant. These announcements about your service will be sent to your Auth0 dashboard and depending on the severity of the announcement, via email to the registered Auth0 dashboard administrators. You should make a regular practice of logging in to the dashboard and checking the bell icon at the top for any important notices. In addition, you should review emails from Auth0 in a timely fashion as they may convey important information about changes or actions you need to take.
+
+### Auth0 security bulletins
+
+Auth0 regularly conducts a number of security-related tests, and if any issues are found, will proactively identify and notify customers who need to make security-related changes. Due to the extensible nature of the Auth0 product, however, it may not be possible for Auth0 to identify every impacted customer, so you should regularly check Auth0 [security bulletins](/security/bulletins). You should make sure a security contact for your organization is listed in Support Center.
+
+::: panel Best Practice
+It is a best practice to check the Auth0 [Security Bulletins](/security/bulletins) page periodically and take the recommended action if you are impacted by any security bulletins.
+:::
+
+### Change log
+
+Auth0 provides information on changes to the service in the Auth0 [change log](https://auth0.com/changelog). You should make a regular practice of reviewing Auth0 change logs to be aware of changes. Support teams researching an issue may find it useful to review the change log to determine if recent changes might be related, especially if these are [breaking changes](/migrations). Development teams will also want to review the change logs to identify new features that may be beneficial.
diff --git a/articles/architecture-scenarios/_includes/_operations/_service-status.md b/articles/architecture-scenarios/_includes/_operations/_service-status.md
new file mode 100644
index 0000000000..a42bdbd948
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_operations/_service-status.md
@@ -0,0 +1,7 @@
+The Auth0 [status dashboard](https://status.auth0.com/) together with the Auth0 [uptime dashboard](http://uptime.auth0.com/) shows current and past status of the Auth0 service in a human-readable format. If any monitoring alerts are triggered, and as a first step in troubleshooting, your operations staff should check the status dashboard to see if there is a current outage. The public cloud status page also provides a facility for subscribing to outage notifications, and we also recommend that you check the status of any 3rd party, [external services](/monitoring/guides/check-external-services) you depend on - such as Social Providers. Having this information handy can help quickly eliminate possible causes when troubleshooting an issue and should be at the top of a troubleshooting checklist for developers as well as the helpdesk staff.
+
+::: panel Best Practice
+Information on how to check the status of Auth0 as well as any dependent services (such as Social Providers) should be at the top of a troubleshooting checklist for both developers and helpdesk staff, and we recommend you subscribe via the Auth0 status page to set up notification of any status updates.
+:::
+
+In the event of an outage to the public cloud service, Auth0 performs a Root Cause Analysis (RCA) and publishes the results on the [Auth0 status page](/support#auth0-status). Auth0 performs a thorough investigation after an outage--including a determination of root cause, as well as contributing factors and how to prevent the issue from occurring again--and as a result, an RCA document can take a few weeks to be published.
diff --git a/articles/architecture-scenarios/_includes/_planning.md b/articles/architecture-scenarios/_includes/_planning.md
new file mode 100644
index 0000000000..8ad9191355
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_planning.md
@@ -0,0 +1,9 @@
+We provide planning guidance in PDF format that you can download and refer to for details about our recommended strategies.
+
+<% if (platform === "b2b") { %>
+B2B IAM Project Planning Guide
+<% } %>
+
+<% if (platform === "b2c") { %>
+B2C IAM Project Planning Guide
+<% } %>
diff --git a/articles/architecture-scenarios/_includes/_profile-mgmt/_account-verification.md b/articles/architecture-scenarios/_includes/_profile-mgmt/_account-verification.md
new file mode 100644
index 0000000000..0306b71049
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_profile-mgmt/_account-verification.md
@@ -0,0 +1,3 @@
+You’ll also need to work with a verified user account at all times and make use of the mechanisms Auth0 provides. You should also consider regulatory compliance like [GDPR](https://eugdpr.org/) which has very specific requirements for protecting EU citizens from privacy and data breaches.
+
+Auth0 provides out-of-box functionality for sending a [verification email](/email/custom#verification-email) to a user's email address to verify their account. By default, Auth0 automatically sends verification emails for any [Database Connection](/connections/database) identity created as part of [self sign-up](/architecture-scenarios/implementation/${platform}/${platform}-provisioning#self-sign-up). However, Auth0 also provides a [Management API endpoint](/api/v2#!/Tickets/post_email_verification) that you can use to send verification emails in cases where email address validation is not performed by a Social Provider upon user registration.
diff --git a/articles/architecture-scenarios/_includes/_profile-mgmt/_blocking-users.md b/articles/architecture-scenarios/_includes/_profile-mgmt/_blocking-users.md
new file mode 100644
index 0000000000..d66954e4a6
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_profile-mgmt/_blocking-users.md
@@ -0,0 +1,3 @@
+[Blocking user access](/users/guides/block-and-unblock-users) in Auth0 provides a way to prevent user login to applications under certain conditions. By default, the Auth0 Dashboard provides an out-of-the-box mechanism to give administrators the ability to both block and unblock user access to all applications, and you can implement this functionality via use of the [Auth0 Management API](/api/management/v2#!/Users/patch_users_by_id). You can also use Auth0 extensibility to [disable user access to certain applications](/users/guides/manage-user-access-to-applications) as well as provide more fine-grained [access control](/architecture-scenarios/implementation/${platform}/${platform}-authorization).
+
+In addition, the Auth0 Management API provides you with the ability to [unblock](/api/management/v2#!/User_Blocks/delete_user_blocks_by_id) users disabled due to excessive use of incorrect credentials.
diff --git a/articles/architecture-scenarios/_includes/_profile-mgmt/_de-provisioning.md b/articles/architecture-scenarios/_includes/_profile-mgmt/_de-provisioning.md
new file mode 100644
index 0000000000..cfbccfab6c
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_profile-mgmt/_de-provisioning.md
@@ -0,0 +1,7 @@
+Your application may need to support a user’s request to remove their account (for example, you might need to meet [GDPR](https://eugdpr.org/) requirements). You can implement such a feature, along with a number of other profile-related functions, using the [Management API](/api/management/v2#!/Users). The Management API allows you to retrieve information stored about a user and update it as required.
+
+Auth0 is capable of supporting various privacy-related requirements including the display of links to consent notices on signup and data protection to support the rights of users to view and correct data you’ve collected about them.
+
+::: note
+[GDPR](https://eugdpr.org/) and other privacy directives require that users have the right to view and correct data held about them. They also have the right to be “forgotten.” You can use the Management API to address these requirements and meet your legislative obligations.
+:::
diff --git a/articles/architecture-scenarios/_includes/_profile-mgmt/_introduction.md b/articles/architecture-scenarios/_includes/_profile-mgmt/_introduction.md
new file mode 100644
index 0000000000..d0098b386d
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_profile-mgmt/_introduction.md
@@ -0,0 +1,49 @@
+At some point, you may need to change the information stored in a user’s [profile](/users/concepts/overview-user-profile). A user’s profile (also known as the user’s account) is stored in Auth0, and changes to the information it contains may need to happen for a number of different reasons:
+
+* Self-served information updates
+* Mandatory updates concerning your organizations T's & C’s
+* Changes due to regulatory compliance
+
+::: warning
+You cannot directly access a user profile across multiple Auth0 tenants. If you’re deploying multiple Auth0 tenants to production then this is something you need to be aware of.
+:::
+
+An [Identity Provider](/identityproviders) populates a user’s profile using data supplied during the login process, and this is referred to as the [Normalized User Profile](/users/normalized/auth0).
+
+::: note
+The Normalized User Profile is updated from the identity provider during login, and you can change the limited set of the information it contains through the Auth0 Management API. You can also use Auth0 extensibility, such as [Rules](/rules), as an alternative to override information in the Normalized User Profile. See [User Profile Data Modification](/users/concepts/overview-user-profile#user-profile-data-modification) for more information.
+:::
+
+By default, there is one user profile created for each user identity, and there are a number of things to consider:
+
+* What should you do if you need to store information to help customize a user’s experience?
+* What if you need to store user information that didn’t originate from an identity provider?
+* Why would you need to store user-related information that a user cannot modify?
+* What do you do if you need to store user-related information that a user cannot modify?
+* What happens if a user forgets their password?
+* What should a user do if they want to change their password?
+<% if (platform === "b2b") { %>
+* How do you provide an administrator from a third-party organization with the ability to manage their users?
+<% } %>
+
+Auth0 provides for the storage of [Metadata](#metadata) against a user’s profile, which allows for the capture of additional information, such as preference for language and/or accessibility in order to enhance the user experience. Metadata can be used to store both information that a user can change, and also information they can’t; the latter giving you the capability of associating, for example, a user profile with records in your existing systems without modifying existing implementation.
+
+For users who forget their passwords or who are allowed to change their password via some existing self-service mechanism (or self-service mechanism you have planned), you can leverage Auth0-provided [Password Reset](#password-reset) functionality. This can be integrated with your existing implementation and comes already incorporated with any out-of-box Auth0 UI widgets including [Universal Login](/universal-login).
+
+You’ll also want to make sure that you are working with a [verified user account](#account-verification) at all times. Auth0 provides out-of-box mechanisms for doing that too. You should also consider [regulatory compliance](/compliance) such as ([GDPR](https://eugdpr.org/) which has very specific requirements when it comes to protecting EU citizens from privacy and data breaches.
+
+Though Auth0 doesn’t currently provide a centralized profile management portal out-of-the-box, for the purpose of self-serviced profile management, you can use the Auth0 Management API to build your own or utilize an already built UI. See our Auth0 [community guidance](https://community.auth0.com/t/how-to-allow-the-end-user-to-update-their-own-profile-information/6228)which describes the Management API endpoint. All calls to the Management API will require use of an [Access Token](/tokens/concepts/access-tokens).
+
+::: warning
+Self-service profile management can raise security as well as data privacy concerns. For example, you may want to allow a user to change their email address, however, doing so without following best practice security guidance could result in a user locking themselves out of their account, leaking Personally Identifiable Information (PII), or worse, opening up a potential breach in security.
+:::
+
+Alternatively, you can use the Auth0 Dashboard to [manage aspects of a user’s profile](users/guides/manage-users-using-the-dashboard). Managing a user’s profile via the Auth0 Dashboard is more of an administrative provision and **should not** be used for self-serviced profile management in a production environment. However, the interface provided by the Dashboard can be extremely useful during development as it provides a quick and simple way of manipulating a user’s profile information.
+
+<% if (platform === "b2b") { %>
+If you need to provide a way for your customers to have an administrator manage their own users when they are storing those credentials in your system, you can either build something yourself or use an Auth0 Extension. See [Admin Portal](#admin-portal) for more information.
+<% } %>
+
+::: panel Get Started with Auth0 Video
+Watch this video [User Profiles](/videos/get-started/06-user-profiles) to learn what Auth0 User Profiles are used for and what they contain. Understand how Auth0 normalizes user profile data from various identity providers and uses metadata and root attributes. You can manage user profiles with the Auth0 Dashboard.
+:::
diff --git a/articles/architecture-scenarios/_includes/_profile-mgmt/_linking-accounts.md b/articles/architecture-scenarios/_includes/_profile-mgmt/_linking-accounts.md
new file mode 100644
index 0000000000..572f16a38e
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_profile-mgmt/_linking-accounts.md
@@ -0,0 +1,9 @@
+By default, there is one [user profile](/users/concepts/overview-user-profile) (user account) for each user identity. If you enable login from multiple identity providers - via Facebook or Google [social authentication](/architecture-scenarios/implementation/${platform}/${platform}-authentication#social-authentication) as well as via Auth0 [username and password authentication](/architecture-scenarios/implementation/${platform}/${platform}-authentication#username-and-password-authentication) - then each will have a separate user profile. You can use Auth0’s functionality for [linking user accounts](/users/concepts/overview-user-account-linking) to create one profile for a user as an aggregate of all their associated identities.
+
+The process of linking accounts merges user profiles in pairs: a primary account and a secondary account must be specified in the linking process. The number of accounts that can be linked, however, extends beyond a single pair. For example, you can use an account which already has multiple accounts merged with it as the primary, and link an additional secondary account to it. This means that one user account can have multiple identities associated with it, which provides a number of advantages:
+
+* Users can log in using multiple identities without creating a separate profile for each one.
+* Registered users can use new login identities, but continue using their existing profile.
+* Users can carry their profile around, irrespective of which identity they use for login.
+* Users can link to an account with more identity information in order to provide a more complete profile.
+* Your applications can retrieve connection-specific user profile data.
diff --git a/articles/architecture-scenarios/_includes/_profile-mgmt/_metadata.md b/articles/architecture-scenarios/_includes/_profile-mgmt/_metadata.md
new file mode 100644
index 0000000000..8fe125d585
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_profile-mgmt/_metadata.md
@@ -0,0 +1,23 @@
+In addition to the Normalized User Profile information, [Metadata](/users/concepts/overview-user-metadata) can be stored in an Auth0 user profile. Metadata provides a way to store information that did not originate from an identity provider, or a way to store information that overrides what an identity provider supplies.
+
+::: panel Best Practice
+Use of Metadata should follow Auth0 [user data storage best practices](/best-practices/user-data-storage-best-practices#metadata). Metadata storage is not designed to be a general purpose data store, and you should still use your own external storage facility when possible. Metadata size and complexity should also be kept to a minimum, and the Auth0 Management API has a strict set of guidance when it comes to updating and/or deleting metadata associated with a user.
+:::
+
+You can manipulate metadata via both the Auth0 Management API and the Auth0 Authentication API. See [Manage User Metadata](/users/guides/manage-user-metadata) for more information. As is the case when managing the Normalized User Profile, calls to the Management API for manipulating Metadata requires use of an [Access Token](api/management/v2/tokens).
+
+::: warning
+<%= include('../../_includes/_rate-limit-policy.md') %>
+:::
+
+### User metadata
+
+User metadata (also referred to as `user_metadata`) is information that can be stored against a user profile and that a user can read and update as part of any self-service profile management. Metadata of this nature may be something like salutation for a user, or a user’s preferred language which could be used to [customize the emails](/email/templates#common-variables) sent by Auth0.
+
+::: panel Best Practice
+Store any information that you want use to customize Auth0 emails in metadata and preferably `user_metadata` if the user is allowed to change it, such as information used to determine the language for an email.
+:::
+
+### App metadata
+
+App metadata (also referred to as `app_metadata`) is, on the other hand, information that can be stored with a user profile but can **only be read or updated with appropriate authorization**; `app_metadata` is not directly accessible to a user. This type of metadata could be something like a flag to indicate that the last set of valid terms and conditions was accepted by the user, and a date to indicate when the user accepted them.
diff --git a/articles/architecture-scenarios/_includes/_profile-mgmt/_password-reset.md b/articles/architecture-scenarios/_includes/_profile-mgmt/_password-reset.md
new file mode 100644
index 0000000000..0407264659
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_profile-mgmt/_password-reset.md
@@ -0,0 +1,9 @@
+For users who forget their passwords or who are allowed to change their password via some existing self-service mechanism, Auth0 provides [Password Reset](/connections/database/password-change) functionality. You can integrate this with your existing implementation and comes already incorporated with out-of-the-box Auth0 UI widgets included as part of [Universal Login](/universal-login).
+
+::: warning
+Password change and password reset is only supported for Auth0 [Database Connection](/connections/database) types.
+:::
+
+Auth0 Universal Login provides built-in UX support for password reset using Auth0 Authentication API functionality. Alternatively, you can use the [Auth0 Authentication API](/connections/database/password-change#use-the-authentication-api), through one of the Auth0 SDKs appropriate to your development environment. Email templates used during password reset workflow can also be fully customized, whether you use Auth0 out-of-box UI widgets or customized Universal Login.
+
+You can use the Auth0 Management API, on the other hand, to [directly change the password](/connections/database/password-change#directly-set-the-new-password) for a user identity defined using a Database Connection type. You can use the Auth0 Management API as part of any self-service profile management implementation, and also as part of any [Change Password page customization](/architecture-scenarios/implementation/${platform}/${platform}-branding#change-password-page-customization).
diff --git a/articles/architecture-scenarios/_includes/_provisioning/_deprovisioning.md b/articles/architecture-scenarios/_includes/_provisioning/_deprovisioning.md
new file mode 100644
index 0000000000..5571357acc
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_provisioning/_deprovisioning.md
@@ -0,0 +1 @@
+Auth0 will *not* communicate with the upstream IdP if there is an active SSO session with Auth0, unless you force it with a `prompt=login`. If one of your customer organizations can not manage logout for those users, they may still have access after they’ve been decommissioned. Depending on the IdP, if Auth0 gets a token for their API, you can request information about the user from the IdP in a [rule](/rules) to poll whether that user should still have access or not. If you don’t have this ability, you will have to provide your customer organizations a way to trigger a block or decommission of users in your system either through an API call or a UI.
diff --git a/articles/architecture-scenarios/_includes/_provisioning/_introduction.md b/articles/architecture-scenarios/_includes/_provisioning/_introduction.md
new file mode 100644
index 0000000000..4a6ec7c089
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_provisioning/_introduction.md
@@ -0,0 +1,33 @@
+Determining how users get signed up is important to address early, and the decisions you make here will influence many of the decisions you will need to make going forward. We’ve found there are a typical set of patterns for how users will get added to your system, and things to take note of when considering workflow design too.
+
+::: panel Best Practice
+Whilst Auth0 supports numerous workflows, web based workflows using Auth0 [Universal Login](/universal-login) for sign up are considered both industry and Auth0 best practice as they provide for optimal functionality and the best security.
+:::
+
+Auth0 supports user sign up via a number of different [identity providers](/identityproviders). During sign up, Auth0 provisions the [user profile](/users/concepts/overview-user-profile) so that it contains the user’s account information. There are a number of things to consider when looking at functionality and workflow:
+
+<% if (platform==="b2b") { %>
+* Does a user get added to your company's domain or do they belong to or remain in their organization's domain?
+* If the user stays in their own domain, do they belong to a single organization or can they belong to multiple organizations?
+* How do you provision the organization itself in your system?
+<% } %>
+* Should you use Auth0 as an identity store?
+* Can you use your own (legacy) identity store with Auth0?
+* How do you migrate user identities from your identity store to Auth0?
+<% if (platform==="b2c") { %>
+* Can your users sign up using their existing social accounts such as Google and Facebook?
+<% } %>
+<% if (platform==="b2b") { %>
+* Can your users sign up using their organization's identity provider?
+* Can your users be invited or self register?
+
+One of the first determinations to make when providing your service(s) to other businesses is identifying to which domain users belong. Based on the answer to that question, there are a couple of different approaches you can take to provision those users. See [Provisioning organization users](#provisioning-organization-users) for more information. Once you know how you want organizations to be represented in your system, you will want too consider how you are going to provision the organization itself. See [Provisioning organizations](#provisioning-organizations) for more information.
+<% } %>
+
+Auth0 provides out-of-the-box identity storage that can be leveraged to store user credentials safely and securely. See [Self Sign Up](#self-sign-up) for more information. If you already have a legacy identity store and you want to offload the management of it, then the [User Migration](#user-migration) capabilities provide you with a number of options to do so.
+
+Alternatively, if you have to maintain your legacy identity store - perhaps because you’ve got applications which you aren’t ready to migrate or which can’t be migrated - then you can use the [identity store proxy](#identity-store-proxy) capability. Allowing your customers to use “bring their own identity” is also an attractive proposition and though we find our customers don’t initially do so, you can use the [Social Sign Up](#social-sign-up) capability to provide it.
+
+::: panel Get Started with Auth0 Videos
+Watch these two short videos [Provision: Users Stores](/videos/get-started/02-provision-user-stores) and [Provision: Import Users](/videos/get-started/03-provision-import-users) to learn how user profiles are provisioned within an Auth0 tenant and how Auth0 allows you to move your existing users to an Auth0 user store.
+:::
diff --git a/articles/architecture-scenarios/_includes/_provisioning/_organizations.md b/articles/architecture-scenarios/_includes/_provisioning/_organizations.md
new file mode 100644
index 0000000000..7dd959ad2c
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_provisioning/_organizations.md
@@ -0,0 +1,30 @@
+::: panel best practice
+What you need to do when provisioning an organization will depend on how organizations are represented in your system. This can take some time to step back and consider how users of those organizations will be interacting with your applications. See [Multiple Organization Architecture](/media/articles/architecture-scenarios/planning/Multiple-Organization-Architecture-Multitenancy-Overview.pdf) to determine how to configure organizations for your IAM system.
+:::
+
+When provisioning organizations you need to consider the following:
+
+* You will need to add the organization to your own application configuration and/or database
+* You will need to make changes to your Auth0 configuration. This will include doing some or all of the following:
+ * Create a unique tenant
+ * Add a database connection (if you have isolated users per organization)
+ * Add an enterprise connection for this organization
+ * This will include working with the organization to either update their existing configuration or add configuration for your Auth0 tenant if they are not a legacy organization.
+ * Provision an administrator for the organization
+* To avoid mistakes, you may want to create an [Organization Admin Portal](#organization-admin-portal) to make it easier to provision new organizations.
+
+### Organization Admin Portal
+An organization admin portal is a portal that allows your administrators to create, modify, and remove organizations. There are multiple activities that need to be done both in your own system and your Auth0 tenant. This portal will likely need to exist in your own system so it has access to your datastores and configuration. However, Auth0 provides the [**Auth0 Management API**](/api/management/v2) so that you can incorporate changes to your Auth0 tenant at the same time that you create the changes in your own system.
+
+There are two main approaches that can be taken for creating a new organization. The one you choose depends highly on your tolerance for how long it would take to deploy a new organization.
+* **Live Updates to your Auth0 Tenant**: If you want to be able to create new organizations in real-time, then you will likely want to make the changes directly to your Auth0 tenant using the Auth0 Management API. This allows the changes to take place in real-time and allow the addition of a new organization to take effect immediately.
+
+::: warning
+ Live Updates do come with some things to consider. There are certain operations that must be done in serial to avoid issues. Enabling clients on a connection, adding callback URL's to an Application are two examples. Any operation in the Management API where you must retrieve an entire list and re-submit the entire list with the new value added to it are operations that must be done in serial to avoid two parallel operations overwriting one of the values.
+:::
+
+* **Change the Repository and Re-deploy**: If you are taking advantage of the Deploy CLI (or a custom CLI) as part of your [CI/CD pipeline]( /architecture-scenarios/implementation/${platform}/${platform}-deployment), you may prefer to push your changes directly to your repository and then kickoff a new deployment instead. This can take a little more time, but it has benefits associated with version history and the ability to backout a change by re-deploying the previous version.
+
+::: panel Best Practice
+You may want to have a separate repository just for the items that the organizations need so that you don't have to re-deploy other common components and risk making an error.
+:::
diff --git a/articles/architecture-scenarios/_includes/_provisioning/_self-signup.md b/articles/architecture-scenarios/_includes/_provisioning/_self-signup.md
new file mode 100644
index 0000000000..6799c34345
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_provisioning/_self-signup.md
@@ -0,0 +1,5 @@
+Self sign up leverages Auth0 [Database Connections](/connections/database) to store the user ID, password, and (optional) username identity information collected from new users during the sign up process. Database connection policies governing things such as minimum [username length](connections/database/require-username#username-length) or [password strength and complexity](/connections/database/password-options) can be configured via the Auth0 Dashboard.
+
+::: panel Best Practice
+Auth0 [Universal Login](/universal-login) as well Auth0 widgets such as [Lock](https://auth0.com/lock) integrate with Database Connections to provide comprehensive user interface functionality for sign up out-of-the-box. These UI artifacts are fully reactive, and with feature rich configuration and comprehensive customization, you can deploy functionality for user self sign up as well as login.
+:::
diff --git a/articles/architecture-scenarios/_includes/_provisioning/_social-signup.md b/articles/architecture-scenarios/_includes/_provisioning/_social-signup.md
new file mode 100644
index 0000000000..c581a3e097
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_provisioning/_social-signup.md
@@ -0,0 +1 @@
+Social signup is synonymous with sign in via [social authentication](/architecture-scenarios/implementation/${platform}/${platform}-authentication#social-authentication) - there’s no distinction here *per se*, as user [profile](/architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt) creation happens automatically upon first social login.
diff --git a/articles/architecture-scenarios/_includes/_provisioning/_user-migration.md b/articles/architecture-scenarios/_includes/_provisioning/_user-migration.md
new file mode 100644
index 0000000000..fea6aca40e
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_provisioning/_user-migration.md
@@ -0,0 +1,17 @@
+In addition to hosting the [User Profile](/architecture-scenarios/implementation/${platform}/${platform}-profile-mgmt), Auth0 also has the capability to both [proxy](#identity-store-proxy) your own legacy identity store and provide a secure Auth0 hosted replacement. Both of these capabilities are supported via the use of Auth0 [Database Connections](/identityproviders#database-and-custom-connections). If you decide to use Auth0 as a replacement for your legacy identity store then you can migrate users either all at once with [Bulk Migration](users/concepts/overview-user-migration#bulk-user-imports-with-the-management-api), or progressively with [Automatic Migration](users/concepts/overview-user-migration#automatic-migrations).
+
+::: panel Best Practice
+Customers often opt for a two-stage approach to user migration, using Automatic Migration first to migrate as many users as possible, then using Bulk Migration for the users that remain. See [User Migration Scenarios](users/references/user-migration-scenarios) for more information.
+:::
+
+Automatic Migration is preferred as it allows users to be migrated individually and also allows them to retain their existing password in almost all situations. For Bulk Migration, we recommend using the [Management API](api/management/v2#!/Jobs/post_users_imports) over the [User Import/Export extension](/users/concepts/overview-user-migration#migrate-users-with-the-user-import-export-extension) in all but the most simple cases, as the Management API provides for greater flexibility and control.
+
+With Bulk Migration users typically need to **reset their password once migration is complete**, _unless_ passwords are stored hashed in your legacy identity store using bcrypt (or you can generate them in bcrypt form). In this case, you _may_ be able to use bulk migration and **preserve user passwords** as part of the process, depending on the bcrypt algorithm and the number of salt rounds used. See [Bulk Import Database Schema Examples](/users/references/bulk-import-database-schema-examples) for more information.
+
+::: panel Best Practice
+<%= include('../../_includes/_rate-limit-policy.md') %>
+:::
+
+### Identity store proxy
+
+Auth0 Database Connection types can also be configured to proxy an existing (legacy) identity store. If you need to keep user identities defined in your own legacy store - for example, if you have one or more business critical applications that you can’t migrate to Auth0, but which still need access to these identities - then you can easily integrate with Auth0. See [Authenticate Users Using Your Database](/connections/database/custom-db) for more information.
diff --git a/articles/architecture-scenarios/_includes/_qa/_integration-testing.md b/articles/architecture-scenarios/_includes/_qa/_integration-testing.md
new file mode 100644
index 0000000000..629c1f9d99
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_qa/_integration-testing.md
@@ -0,0 +1,13 @@
+It is a recommended best practice that you set up different tenants for development, testing, and production as discussed in Architecture guidance for [SDLC support](architecture-scenarios/implementation/${platform}/${platform}-architecture#sdlc-support). Auth0 allows you to configure variables that are available from within custom [extensibility](/topics/extensibility); these can be thought of as environment variables for your Auth0 tenant. Rather than hard code references that change when moving code between development, test, and production environments, you can use a variable name that is configured in the tenant and referenced by the custom extensibility code. This makes it easier for the same custom code to function, without changes, in different tenants as the code can reference variables which will be populated with tenant-specific values at execution time:
+
+* For use of variables in Rules, see how to [configure values](/rules/guides/configuration#configure-values)
+* For use of variables in Hooks, see how to configure [secrets](/hooks/secrets) in the editor
+* For use of variables in Custom DB Scripts, see the [configuration parameters](/connections/database/custom-db/create-db-connection#step-3-add-configuration-parameters)
+
+::: panel Best Practice
+It’s a recommended best practice to use variables to contain tenant-specific values as well as any sensitive secrets that should not be exposed in your custom code. If your custom code is deployed in GitHub, then using a tenant-specific variable avoids exposure of sensitive values via your GitHub repository.
+:::
+
+### Test automation
+
+You can automate your overall build process by incorporating deployment automation as well as test automation. This can be used to deploy new versions of configuration and/or custom code to Auth0 and execute automated tests. If the tests uncover any failures, the deployment automation capabilities can be used to revert to the last working version. For further information, see the [deployment automation guidance](/architecture-scenarios/implementation/${platform}/${platform}-deployment) provided.
diff --git a/articles/architecture-scenarios/_includes/_qa/_introduction.md b/articles/architecture-scenarios/_includes/_qa/_introduction.md
new file mode 100644
index 0000000000..9f423218bc
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_qa/_introduction.md
@@ -0,0 +1,11 @@
+Quality Assurance is important in identifying issues before they impact your customers and, depending on the nature of your project, there are several different types of quality assurance testing that you’re going to want to consider as part of your integration with Auth0:
+
+* Is your application easy to understand and use, even by those with a disability?
+* Does your application need to work across various different browsers and devices?
+* Does your application need to work in multinational and/or international environments?
+* How will your application perform when subjected to unexpected production loads?
+* How can you ensure your application is safe from security-related vulnerabilities?
+
+Auth0 [Universal Login](/universal-login) and associated UI widgets (such as [Lock](/libraries/lock)) have already been designed and built following usability and accessibility best practices, and provide tested out-of-box support for a whole host of [browsers and devices](/support/matrix#browsers). Support for [internationalization](/i18n) (I18N) is also provided out-of-box, with built-in extensibility designed for custom multi-language and localization (L10N) situations.
+
+To ensure functional requirements are met and unexpected events are handled correctly, guidance is provided for testing the [integration](#integration-testing) between your application(s) and Auth0, and for [unit testing](#unit-testing) individual extensibility modules (such as [Rules](/rules/guides/debug#try-this-rule), [Hooks](/hooks/update), and Custom Database scripts). Guidance is also provided regarding Auth0's [penetration testing policy](/policies/penetration-testing) to help when testing for security vulnerability, and also how [Mock](#mock-testing) testing can be leveraged in conjunction with our [load testing policy](/policies/load-testing) to help ensure your application(s) perform under unexpected load.
diff --git a/articles/architecture-scenarios/_includes/_qa/_load-testing.md b/articles/architecture-scenarios/_includes/_qa/_load-testing.md
new file mode 100644
index 0000000000..1761e56882
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_qa/_load-testing.md
@@ -0,0 +1,15 @@
+Load tests require prior approval from Auth0, as explained in the Auth0 [load test policy](/policies/load-testing). Be sure to note the lead time for a request to be reviewed and allow enough time for review as well as conducting the tests. If your load test request has been approved, the following guidance can help avoid errors and faulty test results.
+
+* Run an HTTP trace on a test execution of your application to identify all the calls your application or intended test needs to make, and make sure your test includes them so it is representative of what will happen in production.
+* Design your test to be mindful of Auth0 API rate limits.
+* Use of any custom code in Auth0 (Rules, Custom DB scripts, Hooks, Custom OAuth connections) will invoke the Auth0 custom code sandbox and this may cost more in terms of performance. Turn off Rules unless they are essential to the test. If they are off you will have higher throughput than if they are on.
+* Estimate the expected overall load for your production environment and percent of calls to each endpoint and structure your performance test accordingly so it gives you a realistic test result. Different endpoints have different performance costs. Failure to design a representative test will result in misleading results.
+* Don’t make calls that depend on the results of earlier calls without checking that pre-requisite calls or responses have completed. Simply building in a delay may not be adequate.
+* Be sure to implement adequate error handling. A frequent cause of issues during tests is errors in custom code (rules, hooks, Custom db scripts, Custom OAuth connection scripts) caused by unhandled exceptions in the custom code.
+* Load tests should be written to start at a low level and increase the load gradually, capturing data at each level, to get the most useful results. Starting at a high level and immediately failing gives less information about what the system can sustain.
+* It is normal to need to run a performance test multiple times, possibly adjusting the code under test or the test harness/configuration. Be sure to start your testing early to allow enough time for more than one iteration.
+* Use your own mail provider account and make sure to arrange ahead of time for enough mail-sending quota or you may be rate-limited by the mail provider. Turn off mail sending if you do not use it.
+* Be sure to use your own account credentials for all social connections rather than Auth0 dev keys. In the Auth0 dashboard, go to Connections -> Social -> {name of connection} - to see instructions for how to add your own social provider account credentials into the connection.
+Note: some social providers do not allow load testing. Check your provider(s) for their policy
+* In order to avoid rate limiting, and more accurately simulate real load, your tests will need to send requests for different users, not all requests for the same user. If you use only one or a few users, caching may reduce the effective load and not provide realistic results.
+* Be sure to stay within the agreed-upon parameters for the test and the Auth0 [load test policy](/policies/load-testing). Auth0 reserves the right to terminate any performance/load testing which does not stay within the bounds of agreed-upon parameters or which extends beyond the scheduled test window.
diff --git a/articles/architecture-scenarios/_includes/_qa/_mock-testing.md b/articles/architecture-scenarios/_includes/_qa/_mock-testing.md
new file mode 100644
index 0000000000..786ee3b346
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_qa/_mock-testing.md
@@ -0,0 +1 @@
+In a balance between Auth0’s [load testing policy](/policies/load-testing) and the desire to load test, it is common practice among Auth0’s customers to mock out Auth0’s endpoints. This is a valuable practice in order to ensure that your application works with your expected interfaces without having to restrict your testing, and tools such as [MockServer](http://www.mock-server.com/), [JSON Server](https://github.com/typicode/json-server) or even [Postman](https://learning.getpostman.com/docs/postman/mock_servers/setting_up_mock/) can be used to assist.
diff --git a/articles/architecture-scenarios/_includes/_qa/_unit-testing.md b/articles/architecture-scenarios/_includes/_qa/_unit-testing.md
new file mode 100644
index 0000000000..a8ebd23233
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_qa/_unit-testing.md
@@ -0,0 +1 @@
+The objective of unit testing is to test individual units of code. If you create custom code within Auth0 in the form of Rules, Hooks, and/or Custom DB scripts, you should consider use a testing framework (such as [Mocha](https://mochajs.org/)) to test your code. Companies who have been most successful with Auth0 have found it useful to execute these unit tests prior to [automatically deploying](/architecture-scenarios/implementation/${platform}/${platform}-deployment) Auth0 tenant configuration and collateral.
diff --git a/articles/architecture-scenarios/_includes/_rate-limit-policy.md b/articles/architecture-scenarios/_includes/_rate-limit-policy.md
new file mode 100644
index 0000000000..ce743cf61d
--- /dev/null
+++ b/articles/architecture-scenarios/_includes/_rate-limit-policy.md
@@ -0,0 +1 @@
+Calls to the Management API are subject to [Auth0 Rate Limiting policy](/policies/rate-limits). You must take this into consideration, and to assist, Auth0 generally recommends use of the appropriate [Auth0 SDK](/libraries) for your development environment rather than calling our APIs directly.
diff --git a/articles/architecture-scenarios/application/mobile-api/index.md b/articles/architecture-scenarios/application/mobile-api/index.md
deleted file mode 100644
index db5281bdf1..0000000000
--- a/articles/architecture-scenarios/application/mobile-api/index.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-order: 04
-title: Mobile + API
-image: /media/articles/architecture-scenarios/mobile-api.png
-extract: Mobile application which talks to an API. The application will use OpenID Connect with the Authorization Code Grant using Proof Key for Code Exchange (PKCE) to authenticate users.
-description: Explains the architecture scenario with a mobile application communicating with an API.
-toc: true
----
-
-# Mobile + API
-
-In this scenario we will build a Timesheet API for a fictitious company named ExampleCo. The API will allow management of timesheet entries for an employee or a contractor.
-
-We will also be building a mobile application which will be used to view and log timesheet entries in the centralized timesheet database using the API.
-
-
-::: panel TL;DR
-* Auth0 provides API Authentication and Authorization as a means to secure access to API endpoints (see [API Authentication and Authorization](/architecture-scenarios/application/mobile-api/part-1#api-authentication-and-authorization))
-* For authorizing a mobile app user and granting access to the API, Auth0 supports the Authorization Code Grant Flow with PKCE (see [Proof Key for Code Exchange](/architecture-scenarios/application/mobile-api/part-1#proof-key-for-code-exchange-pkce-))
-* Both the mobile app and the API must be configured in the Auth0 Dashboard (see [Auth0 Configuration](/architecture-scenarios/application/mobile-api/part-2))
-* User Permissions can be enforced using the Authorization Extension (see [Configure the Authorization Extension](/architecture-scenarios/application/mobile-api/part-2#configure-the-authorization-extension))
-* The API is secured by ensuring that a valid [Access Token](/tokens/access-token) is passed in the HTTP Authorization header when calls are made to the API (see [Implement the API](/architecture-scenarios/application/mobile-api/part-3#secure-the-endpoints))
-* The Auth0.Android SDK can be used to authorize the user of the mobile app and obtain a valid Access Token which can be used to call the API (see [Authorize the User](/architecture-scenarios/application/mobile-api/part-3#authorize-the-user))
-* The mobile app can retrieve the user's profile information by decoding the ID Token (see [Get the User Profile](/architecture-scenarios/application/mobile-api/part-3#get-the-user-profile))
-* UI Elements can be displayed conditionally based on the scope that was granted to the user (see [Display UI Elements Conditionally Based on Scope](/architecture-scenarios/application/mobile-api/part-3#display-ui-elements-conditionally-based-on-scope))
-* The mobile app provides the Access Token in the HTTP Authorization header when making calls to the API (see [Call the API](/architecture-scenarios/application/mobile-api/part-3#call-the-api))
-* The mobile app user's Access Token can be renewed to ensure the user does not have to log in again during a session (see [Renew the Token](/architecture-scenarios/application/mobile-api/part-3#renew-the-token))
-:::
-
-## The Premise
-
-ExampleCo is a consulting startup company. Currently they have approximately 100 employees and they also outsource several activities to external contractors. All employees and external contractors are required to fill in their timesheets every week.
-
-The company has built a timesheets application, a scenario we covered in [Single Sign-On for Regular Web Apps](/architecture-scenarios/application/web-app-sso). The internal employees use this web app to fill in their timesheets, but the company wants a mobile application for employees and contractors to use while not on the premises. The app will be used to log timesheet entries and send the data to the centralized timesheet database using the API. The app will also allow managers to approve timesheet entries.
-
-### Goals & Requirements
-
-ExampleCo wants to build a flexible solution. There are potential multiple employees and contractors who should be able to log timesheet entries, as well as batch processes which may upload timesheet entries from other, external systems.
-
-Hence the company has decided to develop a single Timesheets API which will be used to log time not only by this mobile app, but by all other apps as well. They want to put in place a security architecture that is flexible enough to accommodate this. ExampleCo wants to ensure that a large part of the code and business logic for the application can be shared across the different applications.
-
-It is required that only authorized users and applications are allowed access to the Timesheets API.
-
-<%= include('./_stepnav', {
- next: ["1. Solution Overview", "/architecture-scenarios/application/mobile-api/part-1"]
-}) %>
diff --git a/articles/architecture-scenarios/application/mobile-api/part-1.md b/articles/architecture-scenarios/application/mobile-api/part-1.md
deleted file mode 100644
index ffc292f62b..0000000000
--- a/articles/architecture-scenarios/application/mobile-api/part-1.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-description: Solutions Overview for the Mobile + API architecture scenario
-toc: true
----
-
-# Mobile + API: Solutions Overview
-
-<%= include('../../_includes/_api-overview-of-solution.md') %>
-
-<%= include('../../_includes/_api-authentication-and-authorization.md') %>
-
-## Proof Key for Code Exchange (PKCE)
-
-OAuth 2 provides several grant types for different use cases. In this particular use case, we want to access the API from a mobile application, which will use the OAuth 2.0 [Proof Key for Code Exchange](/api-auth/grant/authorization-code-pkce) to do so.
-
-The [Authorization Code Grant](/api-auth/grant/authorization-code) has some security issues, when implemented on native applications. For instance, a malicious attacker can intercept the `authorization_code` returned by Auth0 and exchange it for an [Access Token](/tokens/access-token) (and possibly a [Refresh Token](/tokens/refresh-token)).
-
-The Proof Key for Code Exchange (PKCE) (defined in [RFC 7636](https://tools.ietf.org/html/rfc7636)) is a technique used to mitigate this authorization code interception attack.
-
-With PKCE, the Application creates, for every authorization request, a cryptographically random key called `code_verifier` and its transformed value called `code_challenge`, which is sent to Auth0 to get the `authorization_code`. When the Application receives the `authorization_code`, it will send the code and the `code_verifier` to Auth0's token endpoint to exchange them for the requested tokens.
-
-
-
-1. The native app initiates the flow and redirects the user to Auth0 (specifically to the [/authorize endpoint](/api/authentication#authorization-code-grant-pkce-)), sending the `code_challenge` and `code_challenge_method` parameters.
-2. Auth0 redirects the user to the native app with an `authorization_code` in the querystring.
-3. The native app sends the `authorization_code` and `code_verifier` together with the `redirect_uri` and the `client_id` to Auth0. This is done using the [/oauth/token endpoint](/api/authentication?http#authorization-code-pkce-).
-4. Auth0 validates this information and returns an `access_token` (and optionally a `refresh_token`).
-5. The native app can use the `access_token` to call the API on behalf of the user.
-
-## Authorization Extension
-
-The [Auth0 Authorization Extension](/extensions/authorization-extension) allows you to provide authorization support in your application, by assigning Roles, Groups and Permissions to Users.
-
-The Authorization Extension creates a [Rule](/rules) which will augment the [User profile](/rules/current#rule-syntax) during the authentication flow with the Roles, Groups and Permissions assigned to the user. You can then use this information to ensure that the `access_token` issued to a user only contains scopes which are allowed according to the permissions defined in the Authorization Extension.
-
-<%= include('./_stepnav', {
- prev: ["Introduction", "/architecture-scenarios/application/mobile-api"], next: ["2. Auth0 Configuration", "/architecture-scenarios/application/mobile-api/part-2"]
-}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/application/mobile-api/part-2.md b/articles/architecture-scenarios/application/mobile-api/part-2.md
deleted file mode 100644
index f1b1993815..0000000000
--- a/articles/architecture-scenarios/application/mobile-api/part-2.md
+++ /dev/null
@@ -1,117 +0,0 @@
----
-description: Auth0 Configuration for the Mobile + API architecture scenario
-toc: true
----
-
-# Mobile + API: Auth0 Configuration
-
-In this section we will review all the configurations we need to apply at the [Auth0 Dashboard](${manage_url}).
-
-
-## Create the API
-
-Click on the [APIs menu option](${manage_url}/#/apis) on the left, and click the Create API button.
-
-You will be required to supply the following details for your API:
-
-- __Name__: a friendly name for the API. Does not affect any functionality.
-- __Identifier__: a unique identifier for the API. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all. This value cannot be modified afterwards.
-- __Signing Algorithm__: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting RS256 the token will be signed with the tenant's private key. For more details on the signing algorithms see the Signing Algorithms paragraph below.
-
-
-
-Fill in the required information and click the __Create__ button.
-
-<%= include('../../_includes/_api-signing-algorithms.md') %>
-
-<%= include('../../_includes/_api-configure-scopes.md') %>
-
-## Create the Application
-
-There are four application types in Auth0: __Native__ (used by mobile or desktop apps), __Single Page Web Applications__, __Regular Web Applications__ and __Machine to Machine Application__ (used by CLIs, Daemons, or services running on your backend). For this scenario we want to create a new Application for our mobile application, hence we will use Native as the application type.
-
-To create a new Application, navigate to the [dashboard](${manage_url}) and click on the [Applications](${manage_url}/#/applications}) menu option on the left. Click the __+ Create Application__ button.
-
-Set a name for your Application (we will use `Timesheets Mobile`) and select `Native` as the type.
-
-Click __Create__.
-
-
-
-## Configure the Authorization Extension
-
-You will need to ensure that the Authorization Extension is installed for your tenant. You can refer to the [Authorization Extension documentation](/extensions/authorization-extension#how-to-install) for details on how to do this.
-
-### Define Permissions
-
-You will need to define Permissions which correlates with the scopes you have already defined. In the Authorization Extension, click the _Permissions_ tab, and then click on the **Create Permission** button. In the dialog, capture the details for each permission. Ensure that the name of the permission is exactly the same as the corresponding scope:
-
-
-
-Proceed to create the permissions for all the remaining scopes:
-
-
-
-### Define Roles
-
-Head over to the _Roles_ tab and create 2 Roles. Click the **Create Role** button and select the **Timesheets SPA** application. Give the Role a name and description of Employee, and select the `delete:timesheets`, `create:timesheets` and `read:timesheets` permissons. Click on **Save**.
-
-
-
-Next, follow the same process to create a **Manager** role, and ensure that you have selected all the permissions:
-
-
-
-### Assign Users to Roles
-
-You will need to assign all users to either the Manager or the User role. You can do this by going to the _Users_ tab in the Authorization Extension and selecting a user. On the user information screen, go to the _Roles_ tab. You can add a role to the user by clicking the **Add Role to User** button, and selecting the approproate role for the user.
-
-
-
-### Configuring the Authorization Extension
-
-You will also need to ensure that the Rule for the Authorization Extension is published. You can do this by clicking on your user avatar in to top right of the Authorization Extension, and selecting the **Configuration** option:
-
-
-
-Ensure that you have enabled **Permissions** and then click the **Publish Rule** button:
-
-
-
-### Create a Rule to validate token scopes
-
-The final step in this process is to create a Rule which will validate that the scopes contained in an `access_token` is valid based on the permissions assigned to the user. Any scopes which are not valid for a user should be removed from the `access_token`.
-
-In your Auth0 Dashboard, go to the _Rules_ tab. You should see the Rule created by the Authorization Extension:
-
-
-
-Click on the **Create Rule** button and select the **Empty Rule** template. You can give the Rule a name, such as **Access Token Scopes**, and then specify the following code for the Rule:
-
-```js
-function (user, context, callback) {
- if (context.clientName !== 'Timesheets SPA') {
- return callback(null, user, context);
- }
-
- var permissions = user.permissions || [];
- var requestedScopes = context.request.body.scope || context.request.query.scope;
- var filteredScopes = requestedScopes.split(' ').filter( function(x) {
- return x.indexOf(':') < 0;
- });
- Array.prototype.push.apply(filteredScopes, permissions);
- context.accessToken.scope = filteredScopes.join(' ');
-
- callback(null, user, context);
-}
-```
-
-The code above will ensure that all Access Tokens will only contain the scopes which are valid according to a user's permissions. Once you are done you can click on the **Save** button.
-
-Rules execute in the order they are displayed on the Rules page, so ensure that the new rule you created is positioned below the rule for the Authorization Extension, so it executes after the Authorization Extension rule:
-
-
-
-<%= include('./_stepnav', {
- prev: ["1. Solution Overview", "/architecture-scenarios/application/mobile-api/part-1"], next: ["3. API + Mobile Implementation", "/architecture-scenarios/application/mobile-api/part-3"]
-}) %>
diff --git a/articles/architecture-scenarios/application/mobile-api/part-3.md b/articles/architecture-scenarios/application/mobile-api/part-3.md
deleted file mode 100644
index 427b2950b2..0000000000
--- a/articles/architecture-scenarios/application/mobile-api/part-3.md
+++ /dev/null
@@ -1,201 +0,0 @@
----
-description: API and Mobile Configuration for the Mobile + API architecture scenario
-toc: true
----
-
-# Mobile + API: API and Mobile Configuration
-
-<%= include('../../_includes/_api-implement.md') %>
-
-## Implement the Mobile App
-
-In this section we will see how we can implement a mobile application for our scenario.
-
-::: note
-[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#1-set-up-the-application)
-:::
-
-### Authorize the User
-
-To authorize the user we will implement an [Authorization Code Grant Flow with PKCE](/api-auth/tutorials/authorization-code-grant-pkce). The mobile application should first send the user to the [authorization URL](/api/authentication#authorization-code-grant-pkce-) along with the `code_challenge` and the method used to generate it:
-
-```text
-https://${account.namespace}/authorize?
- audience=API_AUDIENCE&
- scope=SCOPE&
- response_type=code&
- client_id=YOUR_CLIENT_ID&
- code_challenge=CODE_CHALLENGE&
- code_challenge_method=S256&
- redirect_uri=https://YOUR_APP/callback
-```
-
-The `GET` request to the authorization URL should include the following values:
-
-Parameter | Description
-----------|------------
-__client_id__ | The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Auth0 Dashboard](${manage_url}/#/applications).
-__audience__ | The value of your API Identifier. You can retrieve it from the Settings of your API at the [Auth0 Dashboard](${manage_url}/#/apis).
-__scope__ | The [scopes](/scopes) which determine the claims to be returned in the `id_token` and `access_token`. For example, a scope of `openid` will return an `id_token` in the response. In our example mobile app, we use the following scopes: `create:timesheets read:timesheets openid profile email offline_access`. These scopes allow the mobile app to call the API, obtain a `refresh_token`, and return the user's `name`, `picture`, and `email` claims in the `id_token`.
-__response_type__ | Indicates the Authentication Flow to use. For a mobile application using PKCE, this should be set to `code`.
-__code_challenge__ | The generated code challenge from the code verifier. You can find instructions on generating a code challenge [here](/api-auth/tutorials/authorization-code-grant-pkce#1-create-a-code-verifier).
-__code_challenge_method__ | Method used to generate the challenge. Auth0 supports only `S256`.
-__redirect_uri__ | The URL which Auth0 will redirect the browser to after authorization has been granted by the user. The Authorization Code will be available in the code URL parameter. This URL must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications).
-
-::: note
-[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#2-authorize-the-user)
-:::
-
-### Get the Credentials
-
-After a successful request to the authorization URL, you should receive the following response:
-
-```text
-HTTP/1.1 302 Found
-Location: https://${account.namespace}/callback?code=AUTHORIZATION_CODE
-```
-
-Next you can exchange the `authorization_code` from the response for an Access Token that can be used to call your API. Perform a `POST` request to the [Token URL](/api/authentication#authorization-code-pkce-) including the following data:
-
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/oauth/token",
- "headers": [
- { "name": "Content-Type", "value": "application/json" }
- ],
- "postData": {
- "mimeType": "application/json",
- "text": "{\"grant_type\":\"authorization_code\",\"client_id\": \"${account.clientId}\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"com.myclientapp://myclientapp.com/callback\", }"
- }
-}
-```
-
-Parameter | Description
-----------|------------
-__grant_type__ | This must be set to `authorization_code`.
-__client_id__ | The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Auth0 Dashboard](${manage_url}/#/applications).
-__code_verifier__ | Cryptographically random key that was used to generate the `code_challenge` passed to [authorization URL](/api/authentication#authorization-code-grant-pkce-) (`/authorize`).
-__code__ | The `authorization_code` received from the previous authorize call.
-__redirect_uri__ | The URL must match the `redirect_uri` passed in the previous section to `/authorize`.
-
-The response from the Token URL will contain:
-
-```json
-{
- "access_token": "eyJz93a...k4laUWw",
- "refresh_token": "GEbRxBN...edjnXbL",
- "id_token": "eyJ0XAi...4faeEoQ",
- "token_type": "Bearer",
- "expires_in":86400
-}
-```
-
-- __access_token__: An `access_token` for the API, specified by the `audience`.
-- __refresh_token__: A [Refresh Token](/tokens/refresh-token/current) will only be present if you included the `offline_access` scope AND enabled __Allow Offline Access__ for your API in the Dashboard.
-- __id_token__: An `id_token` JWT containing user profile information.
-- __token_type__: A string containing the type of token, this will always be a Bearer token.
-- __expires_in__: The amount of seconds until the `access_token` expires.
-
-You will need to store the above credentials in local storage for use in calling your API and retrieving the user profile.
-
-::: note
-[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#store-credentials)
-:::
-
-### Get the User Profile
-
-To retrieve the [User Profile](/api/authentication?http#user-profile), your mobile application can decode the [ID Token](/tokens/id-token) using one of the [JWT libraries](https://jwt.io/#libraries-io). This is done by [verifying the signature](/tokens/id-token#verify-the-signature) and [validating the claims](/tokens/id-token#validate-the-claims) of the token. After validating the ID Token, you can access its payload containing the user information:
-
-```json
-{
- "email_verified": false,
- "email": "test.account@userinfo.com",
- "clientID": "q2hnj2iu...",
- "updated_at": "2016-12-05T15:15:40.545Z",
- "name": "test.account@userinfo.com",
- "picture": "https://s.gravatar.com/avatar/dummy.png",
- "user_id": "auth0|58454...",
- "nickname": "test.account",
- "created_at": "2016-12-05T11:16:59.640Z",
- "sub": "auth0|58454..."
-}
-```
-
-::: note
-[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#3-get-the-user-profile)
-:::
-
-### Display UI Elements Conditionally Based on Scope
-
-Based on the `scope` of the user, you may want to show or hide certain UI elements. To determine the scope issued to a user, you will need to inspect the the `scope` which was granted when the user was authenticated. This will be a string containing all the scopes, so you therefore need to inspect this string to see whether it contains the required `scope` and based on that make a decision whether to display a particular UI element.
-
-::: note
-[See the implementation in Android](/architecture-scenarios/application/mobile-api/mobile-implementation-android#4-display-ui-elements-conditionally-based-on-scope)
-:::
-
-### Call the API
-
-To access secured resources from your API, the authenticated user's `access_token` needs to be included in requests that are sent to it. This is accomplished by sending the `access_token` in an `Authorization` header using the `Bearer` scheme.
-
-::: note
-[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#5-call-the-api)
-:::
-
-### Renew the Token
-
-::: warning
-Refresh Tokens must be stored securely by an application since they do not expire and allow a user to remain authenticated essentially forever. If Refresh Tokens are compromised or you no longer need them, you can revoke the Refresh Tokens using the [Authentication API](/api/authentication#revoke-refresh-token).
-:::
-
-To refresh your `access_token`, perform a `POST` request to the `/oauth/token` endpoint using the `refresh_token` from your authorization result.
-
-A [Refresh Token](/tokens/refresh-token/current) will only be present if you included the `offline_access` scope in the previous authorization request and enabled __Allow Offline Access__ for your API in the Dashboard.
-
-Your request should include:
-
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/oauth/token",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [
- { "name": "Content-Type", "value": "application/json" }
- ],
- "queryString" : [],
- "postData" : {
- "mimeType": "application/json",
- "text" : "{ \"grant_type\": \"refresh_token\", \"client_id\": \"${account.clientId}\", \"refresh_token\": \"YOUR_REFRESH_TOKEN\" }"
- },
- "headersSize" : 150,
- "bodySize" : 0,
- "comment" : ""
-}
-```
-
-Parameter | Description
-----------|------------
-__grant_type__ | This must be set to `refresh_token`.
-__client_id__ | The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Auth0 Dashboard](${manage_url}/#/applications).
-__refresh_token__ | the `refresh_token` to use, from the previous authentication result.
-
-The response will include the new `access_token`:
-
-```json
-{
- "access_token": "eyJz93a...k4laUWw",
- "refresh_token": "GEbRxBN...edjnXbL",
- "id_token": "eyJ0XAi...4faeEoQ",
- "token_type": "Bearer",
- "expires_in":86400
-}
-```
-
-::: note
-[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#store-the-credentials)
-:::
-
-<%= include('./_stepnav', {
- prev: ["2. Auth0 Configuration", "/architecture-scenarios/application/mobile-api/part-2"], next: ["Conclusion", "/architecture-scenarios/application/mobile-api/part-4"]
-}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/application/mobile-api/part-4.md b/articles/architecture-scenarios/application/mobile-api/part-4.md
deleted file mode 100644
index 7dd6a93185..0000000000
--- a/articles/architecture-scenarios/application/mobile-api/part-4.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-description: Conclusion for the Mobile + API architecture scenario
----
-
-# Mobile + API: Conclusion
-
-In this document we covered a simple scenario: an API, used by a mobile application to allow employees to capture their timesheets.
-
-We learned about the Authorization Code Grant with PKCE, what an Access Token is, how to configure an API in Auth0, how to configure a mobile application to communicate securely with this API, how to define and secure our API endpoints, how to use the provided libraries to validate the Access Token and how to retrieve a new one from Auth0.
-
-We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
-
-We used Node.js for the API implementation and Android for the mobile application. Hopefully though after going through this document you are able to build this using the technologies you prefer.
-
-Don't forget to check back for new business cases and more complex architecture scenarios!
-
-<%= include('./_stepnav', {
- prev: ["3. API + Mobile Implementation", "/architecture-scenarios/application/mobile-api/part-3"]
-}) %>
diff --git a/articles/architecture-scenarios/application/server-api/index.md b/articles/architecture-scenarios/application/server-api/index.md
deleted file mode 100644
index a07f61ce7b..0000000000
--- a/articles/architecture-scenarios/application/server-api/index.md
+++ /dev/null
@@ -1,37 +0,0 @@
----
-order: 02
-title: Server Application + API
-image: /media/articles/architecture-scenarios/server-api.png
-extract: Server to server communication where a server “Application” needs to make secure calls to an API (“Resource Server”), but on behalf of the application vs. a user.
-description: Explains the architecture scenario with server to server communication with secure calls to an API (“Resource Server”), but on behalf of the application vs. a user.
-toc: true
----
-
-# Server + API
-
-In this scenario we will build a Timesheet API for a fictitious company named ExampleCo. The API will allow to add timesheet entries for an employee or a contractor.
-
-We will also be building a cron job which will process timesheet entries from an external system to the centralized timesheet database using the API.
-
-::: panel TL;DR
-* Auth0 provides API Authentication and Authorization as a means to secure access to API endpoints (see [API Authentication and Authorization](/architecture-scenarios/application/server-api/part-1#api-authentication-and-authorization))
-* For authorizing a Machine to Machine Application (a CLI, service or daemon where no user interaction is involved) Auth0 supports the Client Credentials grant (see [Client Credentials Grant](/architecture-scenarios/application/server-api/part-1#client-credentials-grant))
-* Both the Machine to Machine Application and the API must be configured in the Auth0 Dashboard (see [Auth0 Configuration](/architecture-scenarios/application/server-api/part-2))
-* The API will be secured by ensuring that a valid Access Token (which is implemented as a JSON Web Token) is passed in the HTTP Authorization header when calls are made to the API (see [Implement the API](/architecture-scenarios/application/server-api/part-3))
-* Upon successful authorization an Access Token is issued to the Machine to Machine Application (see [Get an Access Token](/architecture-scenarios/application/server-api/part-3#get-an-access-token))
-* The Machine to Machine Application can in turn use this Access Token to pass along as an HTTP Authorization header to authenticate calls to API endpoints (see [Invoke the API](/architecture-scenarios/application/server-api/part-3#invoke-the-api))
-:::
-
-## The Premise
-
-ExampleCo is a consulting startup company. Currently they have approximately 100 employees and they also outsource several activities to external contractors. All employees and external contractors are required to fill in their timesheets every week. For this purpose, they built a timesheets application, a scenario we covered in [Single Sign-On for Regular Web Apps](/architecture-scenarios/application/web-app-sso). The internal employees use this web app to fill in their timesheets but some of the external contractors already use another tool to track their timesheets. Hence a solution to avoid the double work is required. It was decided to build a cron job which will read the timesheet entries from this external system, and automatically upload those to ExampleCo's backend using an API.
-
-### Goals & Requirements
-
-ExampleCo wants to build a flexible solution. At the moment only an automated process needs to push timesheet entries but in the future the company plans on launching more applications, like a mobile app to accommodate their sales teams. Hence the company has decided to develop a single Timesheets API which will be used to log time not only by this server process, but by all future applications as well. They want to put in place a security architecture that is flexible enough to accommodate this. ExampleCo wants to ensure that a large part of the code and business logic for the application can be shared across the different applications.
-
-It is required that only authorized users and applications are allowed access to the Timesheets API.
-
-<%= include('./_stepnav', {
- next: ["1. Solution Overview", "/architecture-scenarios/application/server-api/part-1"]
-}) %>
diff --git a/articles/architecture-scenarios/application/server-api/part-1.md b/articles/architecture-scenarios/application/server-api/part-1.md
deleted file mode 100644
index 7638816527..0000000000
--- a/articles/architecture-scenarios/application/server-api/part-1.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-description: Solutions Overview for the Server + API architecture scenario
-toc: true
----
-
-# Server + API: Solution Overview
-
-<%= include('../../_includes/_api-overview-of-solution.md') %>
-
-<%= include('../../_includes/_api-authentication-and-authorization.md') %>
-
-## Client Credentials Grant
-
-OAuth 2 provides several *grant types* for different use cases. In this particular use case where a cron job will be uploading timesheets via an API, there is no interactive user (or resource owner) who grants permission to the cron job to access the API.
-
-The cron job is also not making the API calls on behalf of any user. Instead there is a machine-to-machine authorization and the application (the cron job) makes calls to the Resource Server (the API) on its own behalf.
-
-For situations like this where there is no user interaction involved, the Client Credentials Grant is ideal. With Client Credentials Grant (defined in [RFC 6749, section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)) an Application can directly request an `access_token` from the Authorization Server by using its Client Credentials (a Client Id and a Client Secret). Instead of identifying a Resource Owner, this token will represent the Application itself.
-
-
-
-1. The Application authenticates with the Authorization Server using its Client ID and Client Secret.
-1. The Authorization Server validates this information and returns an `access_token`.
-1. The Application can use the `access_token` to call the Resource Server on behalf of itself.
-
-<%= include('./_stepnav', {
- prev: ["Introduction", "/architecture-scenarios/application/server-api"], next: ["2. Auth0 Configuration", "/architecture-scenarios/application/server-api/part-2"]
-}) %>
diff --git a/articles/architecture-scenarios/application/server-api/part-2.md b/articles/architecture-scenarios/application/server-api/part-2.md
deleted file mode 100644
index c85bab6ade..0000000000
--- a/articles/architecture-scenarios/application/server-api/part-2.md
+++ /dev/null
@@ -1,91 +0,0 @@
----
-description: Auth0 Configuration for the Server + API architecture scenario
-toc: true
----
-
-# Server + API: Auth0 Configuration
-
-In this section we will review all the configurations we need to apply using the [Auth0 Dashboard](${manage_url}).
-
-## Configure the API
-
-Click on the [APIs menu option](${manage_url}/#/apis) on the left, and click the **Create API** button.
-
-You will be required to supply the following details for your API:
-
-- **Name**: a friendly name for the API. Does not affect any functionality.
-- **Identifier**: a unique identifier for the API. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all. This value cannot be modified afterwards.
-- **Signing Algorithm**: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting RS256 the token will be signed with the tenant's private key. For more details on the signing algorithms see the [Signing Algorithms paragraph](#signing-algorithms) below.
-
-
-
-Fill in the required information and click the **Create** button.
-
-### Signing Algorithms
-
-When you create an API you have to select the algorithm your tokens will be signed with. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
-
-::: note
- The signature is part of a JWT. If you are not familiar with the JWT structure please refer to: [JSON Web Tokens (JWTs) in Auth0](/jwt#what-is-the-json-web-token-structure-).
-:::
-
-To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. That algorithm, which is part of the JWT header, is the one you select for your API: `HS256` or `RS256`.
-
-- **RS256** is an [asymmetric algorithm](https://en.wikipedia.org/wiki/Public-key_cryptography) which means that there are two keys: one public and one private (secret). Auth0 has the secret key, which is used to generate the signature, and the consumer of the JWT has the public key, which is used to validate the signature.
-
-- **HS256** is a [symmetric algorithm](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which means that there is only one secret key, shared between the two parties. The same key is used both to generate the signature and to validate it. Special care should be taken in order for the key to remain confidential.
-
-The most secure practice, and our recommendation, is to use **RS256**. Some of the reasons are:
-
-- With RS256 you are sure that only the holder of the private key (Auth0) can sign tokens, while anyone can check if the token is valid using the public key.
-- Under HS256, If the private key is compromised you would have to re-deploy the API with the new secret. With RS256 you can request a token that is valid for multiple audiences.
-- With RS256 you can implement key rotation without having to re-deploy the API with the new secret.
-
-For a more detailed overview of the JWT signing algorithms refer to: [JSON Web Token (JWT) Signing Algorithms Overview](https://auth0.com/blog/json-web-token-signing-algorithms-overview/).
-
-## Configure the Scopes
-
-Once the application has been created you will need to configure the Scopes which applications can request during authorization.
-
-In the settings for your API, go to the *Scopes* tab. In this section you can add all four of the scopes which was discussed before, namely `batch:upload`, `read:timesheets`, `create:timesheets`, `delete:timesheets`, `approve:timesheets`.
-
-::: note
- For the purposes of this document we will only be ever concerned with the `batch:upload` scope, as that is all that is required by the Cron job. For completeness sake we are however adding the necessary scopes which will be required by future applications as well.
-:::
-
-
-
-## Create the Application
-
-When creating an API in the Auth0 Dashboard, a test application for the API will automatically be generated. In the Auth0 Dashboard, navigate to the [Application Section](${manage_url}/#/applications) and you will see the test application for the Timesheets API.
-
-
-
-Go to the settings for the application by clicking on the gear icon, and rename the application to `Timesheets import Job`.
-
-For the cron job you will need a Machine to Machine Application. This test application which was generated when the API was created was automatically configured as a Machine to Machine Application as can be seen in the screenshot below.
-
-
-
-## Configure Application's access to the API
-
-The final part of the Auth0 configuration is to allow the application access to the Timesheets API. Go back to the configuration of the API, and select the *Machine to Machine Application* tab.
-
-You will see the **Timesheets Import Job** application listed, and it should have access to API as can be seen from the switch to the right of the application name which indicates a value of `Authorized`. If it does not indicate that the application is authorized, simply toggle the value of the switch from `Unauthorized` to `Authorized`.
-
-
-
-You will also need to specify which scopes will be included in Access Tokens which are issued to the application when the application authorizes with Auth0.
-
-Expand the settings for the application by clicking on the down arrow to the far right, and you will see the list of available scopes. The cron job will only require the `batch:upload` scope as it will simply create new timesheets based on the timesheet entries in the external system.
-
-Once you have selected the `batch:upload` scope you can save the settings by clicking the **Update** button.
-
-
-
-Now that we have designed our solution and discussed the configurations needed on Auth0 side, we can proceed with the implementation part. That's what the next paragraph is all about, so keep reading!
-
-
-<%= include('./_stepnav', {
- prev: ["1. Solution Overview ", "/architecture-scenarios/application/server-api/part-1"], next: ["3. Application Implementation", "/architecture-scenarios/application/server-api/part-3"]
-}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/application/server-api/part-3.md b/articles/architecture-scenarios/application/server-api/part-3.md
deleted file mode 100644
index 5549f66eee..0000000000
--- a/articles/architecture-scenarios/application/server-api/part-3.md
+++ /dev/null
@@ -1,137 +0,0 @@
----
-description: Application Implementation for the Server + API architecture scenario
-toc: true
----
-
-# Server + API: Application Implementation
-
-In this section of the tutorial, we will take an in-depth look into our API and its associated Machine to Machine Application.
-
-::: note
- For simplicity reasons we will keep our implementation solely focused on the authentication and authorization part. As you will see in the samples the input timesheet entry will be hard-coded and the API will not persist the timesheet entry, simply echo back some of the info.
-:::
-
-## Define the API endpoints
-
-First we need to define the endpoints of our API.
-
-::: panel What is an API endpoint?
-An **API endpoint** is a unique URL that represents an object. In order to interact with this object you need to point your application towards that URL. For example, if you had an API that could return either order or customers, you might configure two endpoints: `/orders` and `/customers`. Your application would interact with these endpoints using different HTTP methods, for example `POST /orders` to create a new order, or `GET /orders` to retrieve the dataset of one or more orders.
-:::
-
-We will configure one single endpoint that will be used for creating timesheet entries. The endpoint will be `/timesheets/upload` and the HTTP method `POST`.
-
-The API will expect a JSON object as input, containing the timesheet information. We will use the following JSON:
-
-```json
-{
- 'user_id': '007',
- 'date': '2017-05-10T17:40:20.095Z',
- 'project': 'StoreZero',
- 'hours': 5
-}
-```
-
-The API will print the JSON, so we can verify the contents and echo back a message like the following: `Created timesheet 14 for employee 007`.
-
-::: note
- See the implementation in [Node.js](/architecture-scenarios/application/server-api/api-implementation-nodejs#1-define-the-api-endpoint)
-:::
-
-### Secure the API endpoints
-
-::: panel-warning Configure the API
-In order to secure your endpoints you need to have your API configured in the Auth0 Dashboard. For information on how to do that refer to the [Configure the API](#configure-the-api) paragraph of this document.
-:::
-
-The first step towards securing our API endpoint is to get an Access Token as part of the Header and validate it. If it's not valid then we should return an HTTP Status 401 (Unauthorized) to the calling process.
-
-::: note
- See the implementation in [Node.js](/architecture-scenarios/application/server-api/api-implementation-nodejs#2-secure-the-api-endpoint)
-:::
-
-#### Get an Access Token
-
-To get an Access Token without using our application sample implementation, perform a `POST` operation to the `https://${account.namespace}/oauth/token` endpoint with a payload in the following format:
-
-```json
-{
- audience: "YOUR_API_IDENTIFIER",
- grant_type: "client_credentials",
- client_id: "${account.client_id}",
- client_secret: "${account.client_secret}"
-}
-```
-
-::: note
- For more information on this refer to: [API Authorization: Asking for Access Tokens for a Client Credentials Grant](/api-auth/config/asking-for-access-tokens).
-:::
-
-## Check the application permissions
-
-Now we have secured our API's endpoint with an Access Token but we still haven't ensured that the process calling the API has indeed the rights to post a new timesheet entry.
-
-As discussed earlier in this doc, each Access Token may include a list of the permissions that have been granted to the client. These permissions are defined using the scope request parameter. For more information on how to configure this refer to the [Configure the Scopes](#configure-the-scopes) paragraph.
-
-For our endpoint we will require the scope `batch:upload`.
-
-::: note
- See the implementation in [Node.js](/architecture-scenarios/application/server-api/api-implementation-nodejs#3-check-the-client-permissions)
-:::
-
-### Implement the Machine to Machine Application
-
-In this section we will see how we can implement a Machine to Machine Application for our scenario.
-
-::: note
- For simplicity reasons we will keep our implementations solely focused on the authentication and authorization part and configure our application to send a single hard-coded timesheet entry to the API. Also, we will print in the console, something we wouldn't do with a server running process.
-:::
-
-### Get an Access Token
-
-We will start by invoking the Auth0 `/oauth/token` API endpoint in order to get an Access Token.
-
-In order to do so we will need the following configuration values:
-
-- **Domain**: The value of your Auth0 Domain. You can retrieve it from the *Settings* of your application at the [Auth0 Dashboard](${manage_url}/#/applications). This value will be a part of the API URL: `https://${account.namespace}/oauth/token`.
-
-- **Audience**: The value of your API Identifier. You can retrieve it from the *Settings* of your API at the [Auth0 Dashboard](${manage_url}/#/apis).
-
-- **Client ID**: The value of your Auth0 application's Id. You can retrieve it from the *Settings* of your application at the [Auth0 Dashboard](${manage_url}/#/applications).
-
-- **Client Secret**: The value of your Auth0 application's Secret. You can retrieve it from the *Settings* of your application at the [Auth0 Dashboard](${manage_url}/#/applications).
-
-Our implementation should perform a `POST` operation to the `https://${account.namespace}/oauth/token` endpoint with a payload in the following format:
-
-```json
-{
- "audience": "YOUR_API_IDENTIFIER",
- "grant_type": "client_credentials",
- "client_id": "${account.client_id}",
- "client_secret": "${account.client_secret}"
-}
-```
-
-For more information on this refer to: [API Authorization: Asking for Access Tokens for a Client Credentials Grant](/api-auth/config/asking-for-access-tokens).
-
-::: note
- See the implementation in [Python](/architecture-scenarios/application/server-api/cron-implementation-python#get-an-access-token).
-:::
-
-## Invoke the API
-
-Now that we have an Access Token, which includes the valid scopes, we can invoke our API.
-
-In order to do so we will:
-- Build a hard-coded timesheet entry in JSON format.
-- Add the Access Token as an `Authorization` header to our request.
-- Make the HTTP POST request.
-- Parse the response and print it in the terminal (optional).
-
-::: note
- See the implementation in [Python](/architecture-scenarios/application/server-api/cron-implementation-python#invoke-the-api).
-:::
-
-<%= include('./_stepnav', {
- prev: ["2. Auth0 Configuration", "/architecture-scenarios/application/server-api/part-2"], next: ["Conclusion", "/architecture-scenarios/application/server-api/part-4"]
-}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/application/server-api/part-4.md b/articles/architecture-scenarios/application/server-api/part-4.md
deleted file mode 100644
index 35ba5464ba..0000000000
--- a/articles/architecture-scenarios/application/server-api/part-4.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-description: Conclusion for the Server + API architecture scenario
-toc: true
----
-
-# Server + API: Conclusion
-
-In this document we covered a simple scenario: an API, used to import timesheet entries in ExampleCo's systems, and a cron job, used by external contractors to send in their timesheets using this API.
-
-We learned about the Client Credentials Grant, what an Access Token is, how to configure an API in Auth0, how to configure a Machine to Machine Application to communicate securely with this API, how to define and secure our API endpoints, how to use the provided libraries to validate the Access Token and how to retrieve a new one from Auth0.
-
-We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
-
-We used Node.js for the API implementation and Python for the non interactive server process, hopefully though after going through this document you are able to build this using the technologies you prefer.
-
-<%= include('./_stepnav', {
- prev: ["3. Application Implementation", "/architecture-scenarios/application/server-api/part-3"]
-}) %>
diff --git a/articles/architecture-scenarios/application/spa-api/index.md b/articles/architecture-scenarios/application/spa-api/index.md
deleted file mode 100644
index 92e1b4dbca..0000000000
--- a/articles/architecture-scenarios/application/spa-api/index.md
+++ /dev/null
@@ -1,44 +0,0 @@
----
-order: 03
-title: SPA + API
-image: /media/articles/architecture-scenarios/spa-api.png
-extract: Single Page Web Application which talks to an API. The application will use OpenID Connect with the Implicit Grant Flow to authenticate users with Auth0.
-description: Explains the architecture scenario where a Single Page Web Application (SPA) talks to an API using OpenID Connect, and the OAuth 2.0 Implicit Grant Flow, to authenticate users with Auth0.
-toc: true
----
-
-# SPA + API
-
-In this scenario, we will build a Timesheet API for a fictitious company named ExampleCo. The API will allow adding timesheet entries for an employee or a contractor.
-
-We will also be building a Single Page Application (SPA) which will be used to log timesheet entries and send them to the centralized timesheet database using the API.
-
-::: panel TL;DR
-* Auth0 provides API Authentication and Authorization as a means to secure access to API endpoints (see [API Authentication and Authorization](/architecture-scenarios/application/spa-api/part-1#api-authentication-and-authorization))
-* For authorizing a user of a SPA, Auth0 supports the Implicit Grant (see [Implicit Grant](/architecture-scenarios/application/spa-api/part-1#implicit-grant))
-* Both the SPA and the API must be configured in the Auth0 Dashboard (see [Auth0 Configuration](/architecture-scenarios/application/spa-api/part-2#auth0-configuration))
-* User Permissions can be enforced using the Authorization Extension (see [Configure the Authorization Extension](/architecture-scenarios/application/spa-api/part-2#configure-the-authorization-extension))
-* The API will be secured by ensuring that a valid Access Token is passed in the HTTP Authorization header when calls are made to the API (see [Implement the API](/architecture-scenarios/application/spa-api/part-3#implement-the-api))
-* The Auth0.js library can be used to authorize the user of the SPA and obtain a valid Access Token which can be used to call the API (see [Authorize the User](/architecture-scenarios/application/spa-api/part-3#authorize-the-user))
-* The SPA can pass the Access Token in the HTTP Authorization header when making calls to the API (see [Call the API](/architecture-scenarios/application/spa-api/part-3#call-the-api))
-* The SPA can display UI elements conditionally based on scopes granted to user (see [Display UI Elements Conditionally Based on Scope](/architecture-scenarios/application/spa-api/part-3#display-ui-elements-conditionally-based-on-scope))
-
-:::
-
-## The Premise
-
-ExampleCo is a consulting startup company. Currently, they have approximately 100 employees and they also outsource several activities to external contractors. All employees and external contractors are required to fill in their timesheets every week.
-
-The company has built a timesheets application, a scenario we covered in [Single Sign-On for Regular Web Apps](/architecture-scenarios/application/web-app-sso). The internal employees use this web app to fill in their timesheets but the company wants to replace it with a SPA. The app will be used to log timesheet entries and send the data to the centralized timesheet database using the API. The app will also allow managers to approve timesheet entries.
-
-## Goals & Requirements
-
-ExampleCo wants to build a flexible solution. At the moment only a SPA is required to capture timesheet entries but in the future, the company plans on launching more applications, like a mobile app to accommodate their sales teams. Hence the company has decided to develop a single Timesheets API which will be used to log time not only by this server process but by all future applications as well. They want to put in place a security architecture that is flexible enough to accommodate this. ExampleCo wants to ensure that a large part of the code and business logic for the application can be shared across the different applications.
-
-It is required that only authorized users and applications are allowed access to the Timesheets API.
-
-Two kinds of users will use this SPA: employees and managers. The employees should be able to read, create and delete their own timesheet entries, while the managers should be able to approve timesheets as well.
-
-<%= include('./_stepnav', {
- next: ["1. Solution Overview", "/architecture-scenarios/application/spa-api/part-1"]
-}) %>
diff --git a/articles/architecture-scenarios/application/spa-api/part-1.md b/articles/architecture-scenarios/application/spa-api/part-1.md
deleted file mode 100644
index fbda32a8d4..0000000000
--- a/articles/architecture-scenarios/application/spa-api/part-1.md
+++ /dev/null
@@ -1,45 +0,0 @@
----
-description: Solution Overview for the SPA + API architecture scenario
-toc: true
----
-
-# SPA + API: Solution Overview
-
-<%= include('../../_includes/_api-overview-of-solution.md') %>
-
-<%= include('../../_includes/_api-authentication-and-authorization.md') %>
-
-## Implicit Grant
-
-OAuth 2.0 provides several __grant types__ for different use cases. In this particular use case, we want to access the API from a [client-side app](/quickstart/spa).
-
-The SPA will use the OAuth 2.0 [Implicit Grant](/api-auth/grant/implicit) to do so.
-
-The Implicit Grant (defined in [RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.2)) is similar to the [Authorization Code Grant](/api-auth/grant/authorization-code), but the main difference is that the application receives an `access_token` directly, without the need for an `authorization_code`. This happens because the application, which is typically a JavaScript app running within a browser, is less trusted than a web app running on the server, hence cannot be trusted with the `client_secret` (which is required in the Authorization Code Grant).
-
-Once the user authenticates, the application receives the `id_token` and `access_token` in the hash fragment of the URI. The application can now use the `id_token` to obtain information about the user, and `access_token` to call the API on behalf of the user.
-
-
-
-1. The app initiates the flow and redirects the browser to Auth0 (specifically to the [/authorize endpoint](/api/authentication#implicit-grant)), so the user can authenticate.
-
-1. Auth0 authenticates the user. The first time the user goes through this flow, and if the application is a third party application, a consent page will be shown where the permissions, that will be given to the Client, are listed (for example, post messages, list contacts, and so forth).
-
-1. Auth0 redirects the user to the app with an `access_token` (and optionally an `id_token`) in the hash fragment of the URI. The app can now extract the tokens from the hash fragment.
-
-1. The app can use the `access_token` to call the API on behalf of the user.
-
-## Authorization Extension
-
-The [Auth0 Authorization Extension](/extensions/authorization-extension) allows you to configure Roles, Groups, and Permissions, and assign them to Users.
-
-- The Permissions are actions that someone can do. For ExampleCo's business needs, we will configure four Permissions: read, create, delete and approve timesheets.
-- The Roles are collections of Permissions. ExampleCo's timesheets app will be used by two kinds of users (employees and managers), with different permissions each, so we will configure two Roles: employee and manager.
-
-Since this covers our business case we will not create any Groups.
-
-The Authorization Extension will create a [Rule](/rules) which will read the Roles, Groups, and Permissions assigned to a user and add this information to the [User profile](/rules/current#rule-syntax) during the authentication flow. We can use this information to ensure that the `access_token` issued to a user only contains scopes which are allowed. We can later on proceed to customize our app, like disabling the Approve Timesheets functionality if the user does not have the required permission to do so.
-
-<%= include('./_stepnav', {
- prev: ["Introduction", "/architecture-scenarios/application/spa-api"], next: ["2. Auth0 Configuration", "/architecture-scenarios/application/spa-api/part-2"]
-}) %>
diff --git a/articles/architecture-scenarios/application/spa-api/part-2.md b/articles/architecture-scenarios/application/spa-api/part-2.md
deleted file mode 100644
index 27e262ac0b..0000000000
--- a/articles/architecture-scenarios/application/spa-api/part-2.md
+++ /dev/null
@@ -1,168 +0,0 @@
----
-description: Auth0 Configuration for the SPA + API architecture scenario
-toc: true
----
-
-# SPA + API: Auth0 Configuration
-
-In this section we will review all the configurations we need to apply at the [Auth0 Dashboard](${manage_url}).
-
-## Create the API
-
-Navigate to the [APIs section](${manage_url}/#/apis) of the dashboard, and click the **Create API** button.
-
-You will be asked to supply the following details for your API:
-
-- __Name__: a friendly name for the API. Does not affect any functionality.
-- __Identifier__: a unique identifier for the API. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all. This value cannot be modified afterwards.
-- __Signing Algorithm__: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting RS256 the token will be signed with the tenant's private key. For more details on the signing algorithms see the [Signing Algorithms paragraph](#signing-algorithms) below.
-
-
-
-Fill in the required information and click the **Create** button.
-
-## Signing Algorithms
-
-When you create an API you have to select the algorithm your tokens will be signed with. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
-
-::: note
-The signature is part of a JWT. If you are not familiar with the JWT structure please refer to [JSON Web Tokens (JWTs) in Auth0](/jwt#what-is-the-json-web-token-structure-).
-:::
-
-To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. That algorithm, which is part of the JWT header, is the one you select for your API: `HS256` or `RS256`.
-
-- __RS256__ is an [asymmetric algorithm](https://en.wikipedia.org/wiki/Public-key_cryptography) which means that there are two keys: one public and one private (secret). Auth0 has the secret key, which is used to generate the signature, and the consumer of the JWT has the public key, which is used to validate the signature.
-
-- __HS256__ is a [symmetric algorithm](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which means that there is only one secret key, shared between the two parties. The same key is used both to generate the signature and to validate it. Special care should be taken in order for the key to remain confidential.
-
-The most secure practice, and our recommendation, is to use __RS256__. Some of the reasons are:
-
-- With RS256 you are sure that only the holder of the private key (Auth0) can sign tokens, while anyone can check if the token is valid using the public key.
-- Under HS256, If the private key is compromised you would have to re-deploy the API with the new secret. With RS256 you can request a token that is valid for multiple audiences.
-- With RS256 you can implement key rotation without having to re-deploy the API with the new secret.
-
-::: note
-For a more detailed overview of the JWT signing algorithms refer to [JSON Web Token (JWT) Signing Algorithms Overview](https://auth0.com/blog/json-web-token-signing-algorithms-overview/).
-:::
-
-## Configure the Scopes
-
-Once the application has been created you will need to configure the Scopes which applications can request during authorization.
-
-In the settings for your API, go to the **Scopes** tab. In this section you can add the scopes for our business case: `read:timesheets`, `create:timesheets`, `delete:timesheets`, and `approve:timesheets`.
-
-
-
-## Create the Application
-
-There are four application types in Auth0:
-- __Native__ (used by mobile or desktop apps),
-- __Single Page Web Applications__,
-- __Regular Web Applications__ and
-- __Machine to Machine Applications__ (used by CLIs, Daemons, or services running on your backend).
-
-For this scenario we want to create a new Application for our SPA, hence we will use Single Page Application as the application type.
-
-To create a new Application, navigate to the [dashboard](${manage_url}) and click on the [Applications](${manage_url}/#/applications}) menu option on the left. Click the __+ Create Application__ button.
-
-Set a name for your Application (we will use `Timesheets SPA`) and select `Single Page Web Applications` as the type.
-
-Click __Create__.
-
-
-
-That's it for now. When we are done with the SPA implementation we will revisit the dashboard and this Application's settings to make some changes in its configuration.
-
-## Configure the Authorization Extension
-
-You will need to ensure that the Authorization Extension is installed for your tenant. You can refer to the [Authorization Extension documentation](/extensions/authorization-extension#how-to-install) for details on how to do this.
-
-### Define Permissions
-
-You will now define the required Permissions, according to the scopes you have already defined: `read:timesheets`, `create:timesheets`, `delete:timesheets`, and `approve:timesheets`.
-
-In the Authorization Extension, click the **Permissions** tab, and then click on the **Create Permission** button.
-
-In the dialog, capture the details for each permission.
-
-Ensure that the name of the permission is exactly the same as the corresponding scope:
-
-
-
-Proceed to create the permissions for all the remaining scopes:
-
-
-
-### Define Roles
-
-Next let's configure the two Roles: employee and manager.
-
-Head over to the **Roles** tab, click the **Create Role** button, and select the **Timesheets SPA** application.
-
-Set the **Name** and **Description** to `Employee`, and select the `delete:timesheets`, `create:timesheets` and `read:timesheets` permissons. Click on **Save**.
-
-
-
-Next, follow the same process to create a `Manager` role, and ensure that you have selected all the permissions.
-
-
-
-### Assign Users to Roles
-
-You need to assign all users to either the `Manager` or the `Employee` role.
-
-You can do this by going to the **Users** tab in the Authorization Extension and selecting a user.
-
-On the user information screen, go to the **Roles** tab. Click **Add Role to User**, and select the appropriate role.
-
-
-
-### Configuring the Authorization Extension
-
-You will also need to ensure that the Rule for the Authorization Extension is published.
-
-To do so, click on your user avatar in the top right of the Authorization Extension, and select **Configuration**.
-
-
-
-Make sure that **Permissions** are enabled and then click **Publish Rule**.
-
-
-
-### Create a Rule to validate token scopes
-
-The final step in this process is to create a Rule which will validate that the scopes contained in an `access_token` is valid based on the permissions assigned to the user. Any scopes which are not valid for a user should be removed from the `access_token`.
-
-In your Auth0 Dashboard, go to the **Rules** tab. You should see the Rule created by the Authorization Extension:
-
-
-
-Click on the **Create Rule** button and select the **Empty Rule** template. You can give the Rule a name, such as **Access Token Scopes**, and then specify the following code for the Rule:
-
-```js
-function (user, context, callback) {
- if (context.clientName !== 'Timesheets SPA') {
- return callback(null, user, context);
- }
-
- var permissions = user.permissions || [];
- var requestedScopes = context.request.body.scope || context.request.query.scope;
- var filteredScopes = requestedScopes.split(' ').filter( function(x) {
- return x.indexOf(':') < 0;
- });
- Array.prototype.push.apply(filteredScopes, permissions);
- context.accessToken.scope = filteredScopes.join(' ');
-
- callback(null, user, context);
-}
-```
-
-The code above will ensure that all Access Tokens will only contain the scopes which are valid according to a user's permissions. Once you are done you can click on the **Save** button.
-
-Rules execute in the order they are displayed on the Rules page, so ensure that the new rule you created is positioned below the rule for the Authorization Extension, so it executes after the Authorization Extension rule:
-
-
-
-<%= include('./_stepnav', {
- prev: ["1. Solution Overview", "/architecture-scenarios/application/spa-api/part-1"], next: ["3. API + SPA Implementation", "/architecture-scenarios/application/spa-api/part-3"]
-}) %>
diff --git a/articles/architecture-scenarios/application/spa-api/part-3.md b/articles/architecture-scenarios/application/spa-api/part-3.md
deleted file mode 100644
index 2a6e8ea77c..0000000000
--- a/articles/architecture-scenarios/application/spa-api/part-3.md
+++ /dev/null
@@ -1,212 +0,0 @@
----
-description: API and SPA Configuration for the SPA + API architecture scenario
-toc: true
----
-
-# SPA + API: API and SPA Configuration
-
-In this section we will see how we can implement an API for our scenario.
-
-::: note
-For simplicity reasons we will keep our implementation solely focused on the authentication and authorization part. As you will see in the samples the input timesheet entry will be hard-coded and the API will not persist the timesheet entry, simply echo back some of the info.
-:::
-
-## Define the API endpoints
-
-First we need to define the endpoints of our API.
-
-::: panel What is an API endpoint?
-An **API endpoint** is a unique URL that represents an object. In order to interact with this object you need to point your application towards that URL. For example, if you had an API that could return either order or customers, you might configure two endpoints: `/orders` and `/customers`. Your application would interact with these endpoints using different HTTP methods, for example `POST /orders` to create a new order, or `GET /orders` to retrieve the dataset of one or more orders.
-:::
-
-For this implementation we will only define 2 endpoints; one for retrieving a list of all timesheets for an employee, and another which will allow an employee to create a new timesheet entry.
-
-An `HTTP GET` request to the `/timesheets` endpoint will allow a user to retrieve their timesheets, and an `HTTP POST` request to the `/timesheets` endpoint will allow a user to add a new timesheet.
-
-::: note
-See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#1-define-the-api-endpoints)
-:::
-
-### Secure the Endpoints
-
-When an API receives a request with a bearer Access Token as part of the header, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request must be rejected with a `Missing or invalid token` error message to the calling app.
-
-The validations that the API should perform are:
-
-- Check that the JWT is well formed
-- Check the signature
-- Validate the standard claims
-
-::: note
-[JWT.io](https://jwt.io/) provides a list of libraries that can do most of the work for you: parse the JWT, verify the signature and the claims.
-:::
-
-Part of the validation process is to also check the Application permissions (scopes), but we will address this separately in the next paragraph of this document.
-
-For more information on validating Access Tokens, refer to [Verify Access Tokens](/api-auth/tutorials/verify-access-token).
-
-::: note
-See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#2-secure-the-api-endpoints)
-:::
-
-### Check the Application's Permissions
-
-By now we have verified that the JWT is valid. The last step is to verify that the application has the permissions required to access the protected resources.
-
-To do so, the API needs to check the [scopes](/scopes) of the decoded JWT. This claim is part of the payload and it is a space-separated list of strings.
-
-::: note
-See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#3-check-the-client-permissions)
-:::
-
-### Determine user identity
-
-For both endpoints (retrieving the list of timesheets, and adding a new timesheet) we will need to determine the identity of the user.
-
-For retrieving the list of timesheets this is to ensure that we only return the timesheets belonging to the user making the request, and for adding a new timesheet this is to ensure that the timesheet is associated with the user making the request.
-
-One of the standard JWT claims is the `sub` claim which identifies the principal that is the subject to the claim. In the case of the Implicit Grant flow this claim will contain the user's identity, which will be the unique identifier for the Auth0 user. You can use this to associate any information in external systems with a particular user.
-
-You can also use a custom claim to add another attribute of the user - such as their email address - to the `access_token` and use that to uniquely identify the user.
-
-::: note
-See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#4-determine-the-user-identity)
-:::
-
-## Implement the SPA
-
-In this section we will see how we can implement a SPA for our scenario.
-
-### Authorize the user
-
-To authorize the user we will be using the [auth0.js library](/libraries/auth0js). You can initialize a new instance of the Auth0 application as follows:
-
-```js
-var auth0 = new auth0.WebAuth({
- clientID: '${account.clientId}',
- domain: '${account.namespace}',
- responseType: 'token id_token',
- audience: 'YOUR_API_IDENTIFIER',
- redirectUri: '${account.callback}',
- scope: 'openid profile read:timesheets create:timesheets'
-});
-```
-
-You need to pass the following configuration values:
-
-- __clientID__:The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Dashboard](${manage_url}/#/applications}).
-- __domain__: The value of your Auth0 Domain. You can retrieve it from the Settings of your Application at the [Dashboard](${manage_url}/#/applications}).
-- __responseType__: Indicates the Authentication Flow to use. For a SPA which uses the __Implicit Flow__, this should be set to `token id_token`. The `token` part, triggers the flow to return an `access_token` in the URL fragment, while the `id_token` part, triggers the flow to return an `id_token` as well.
-- __audience__: The value of your API Identifier. You can retrieve it from the [Settings of your API](${manage_url}/#/apis}) at the Dashboard.
-- __redirectUri__: The URL to which Auth0 should redirect to after the user has authenticated.
-- __scope__: The [scopes](/scopes) which determine the information to be returned in the `id_token` and `access_token`. A scope of `openid profile` will return all the user profile information in the `id_token`. You also need to request the scopes required to call the API, in this case the `read:timesheets create:timesheets` scopes. This will ensure that the `access_token` has these scopes.
-
-To initiate the authentication flow you can call the `authorize()` method:
-
-```js
-auth0.authorize();
-```
-
-After the authentication, Auth0 will redirect back to the __redirectUri__ you specified when configuring the new instance of the Auth0 application. At this point you will need to call the `parseHash()` method which parses a URL hash fragment to extract the result of an Auth0 authentication response.
-
-The contents of the authResult object returned by parseHash depend upon which authentication parameters were used. It may include the following:
-
-- __idToken__: An `id_token` JWT containing user profile information
-- __accessToken__: An `access_token` for the API, specified by the __audience__.
-- __expiresIn__: A string containing the expiration time (in seconds) of the `access_token`.
-
-You also need to store the tokens returned by the authentication result in local storage to keep track of the fact that the user is logged in. You can also subsequently retrieve the `access_token` from local storage when calling your API.
-
-```js
-this.auth0.parseHash((err, authResult) => {
- if (authResult && authResult.accessToken && authResult.idToken) {
- window.location.hash = '';
- // Store the authResult in local storage and redirect the user elsewhere
- localStorage.setItem('access_token', authResult.accessToken);
- localStorage.setItem('id_token', authResult.idToken);
- } else if (err) {
- // Handle authentication error, for example by displaying a notification to the user
- }
-});
-```
-
-::: note
-See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#2-authorize-the-user)
-:::
-
-### Get the User Profile
-
-::: panel Extract info from the token
-This section shows how to retrieve the user info using the `access_token` and the [/userinfo endpoint](/api/authentication#get-user-info). To avoid this API call, you can just decode the `id_token` [using a library](https://jwt.io/#libraries-io) (make sure you validate it first). If you need additional user information consider using [our Management API](/api/management/v2#!/Users/get_users_by_id) from your backend.
-:::
-
-The `client.userInfo` method can be called passing the returned `authResult.accessToken` in order to retrieve the user's profile information. It will make a request to the [/userinfo endpoint](/api/authentication#get-user-info) and return the `user` object, which contains the user's information, similar to the example below:
-
-```json
-{
- "email_verified": "false",
- "email": "test@example.com",
- "clientID": "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH",
- "updated_at": "2017-02-07T20:50:33.563Z",
- "name": "tester9@example.com",
- "picture": "https://gravatar.com/avatar/example.png",
- "user_id": "auth0|123456789012345678901234",
- "nickname": "tester9",
- "created_at": "2017-01-20T20:06:05.008Z",
- "sub": "auth0|123456789012345678901234"
-}
-```
-
-You can access any of these properties in the callback function passed when calling the `userInfo` function:
-
-```js
-const accessToken = localStorage.getItem('access_token');
-
-auth0.client.userInfo(accessToken, (err, profile) => {
- if (profile) {
- // Get the user’s nickname and profile image
- var nickname = profile.nickname;
- var picture = profile.picture;
- }
-});
-```
-
-::: note
-See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#3-get-the-user-profile)
-:::
-
-### Display UI Elements Conditionally Based on Scope
-
-Based on the `scope` of the user, you may want to show or hide certain UI elements. To determine the scope issued to a user, you will need to store the scope which was initially requested during the authorization process. When a user is authorized, the `scope` will also be returned in the `authResult`.
-
-If the `scope` in the `authResult` is empty, then all the scopes which was requested was granted. If the `scope` in the `authResult` is not empty, it means a different set of scopes were granted, and you should use the ones in `authResult.scope`.
-
-::: note
-See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#4-display-ui-elements-conditionally-based-on-scope)
-:::
-
-### Call the API
-
-To access secured resources from your API, the authenticated user's `access_token` needs to be included in requests that are sent to it. This is accomplished by sending the `access_token` in an `Authorization` header using the `Bearer` scheme.
-
-::: note
-See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#5-call-the-api)
-:::
-
-### Renew the Access Token
-
-As a security measure, it is recommended that the lifetime of a user's `access_token` be kept short. When you create an API in the Auth0 dashboard, the default lifetime is `7200` seconds (2 hours), but this can be controlled on a per-API basis.
-
-Once expired, an `access_token` can no longer be used to access an API. In order to obtain access again, a new `access_token` needs to be obtained.
-
-Obtaining a new `access_token` can be done by repeating the authentication flow, used to obtain the initial `access_token`. In a SPA this is not ideal, as you may not want to redirect the user away from their current task to complete the authentication flow again.
-
-In cases like this you can make use of [Silent Authentication](/api-auth/tutorials/silent-authentication). Silent authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page. This does however require that the user was already logged in via [SSO (Single Sign-On)](/sso).
-
-::: note
-See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#6-renew-the-access-token)
-:::
-
-<%= include('./_stepnav', {
- prev: ["2. Auth0 Configuration", "/architecture-scenarios/application/spa-api/part-2"], next: ["Conclusion", "/architecture-scenarios/application/spa-api/part-4"]
-}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/application/spa-api/part-4.md b/articles/architecture-scenarios/application/spa-api/part-4.md
deleted file mode 100644
index 1bd0228d29..0000000000
--- a/articles/architecture-scenarios/application/spa-api/part-4.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-description: Conclusion for the SPA + API architecture scenario
-toc: true
----
-
-# SPA + API: Conclusion
-
-In this document we covered a simple scenario involving an API used by a Single Page Application (SPA) to allow employees to capture their timesheets.
-
-We learned about the Implicit Grant, what an Access Token is, how to configure an API in Auth0, how to configure a SPA application to communicate securely with this API, how to define and secure our API endpoints, how to use the provided libraries to validate the Access Token and how to retrieve a new one from Auth0.
-
-We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
-
-We used Node.js for the API implementation and Angular for the SPA. Hopefully though after going through this document you are able to build this using the technologies you prefer.
-
-<%= include('./_stepnav', {
- prev: ["3. API + SPA Implementation", "/architecture-scenarios/application/spa-api/part-3"]
-}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/application/web-app-sso/index.md b/articles/architecture-scenarios/application/web-app-sso/index.md
deleted file mode 100644
index 4bca57ee11..0000000000
--- a/articles/architecture-scenarios/application/web-app-sso/index.md
+++ /dev/null
@@ -1,66 +0,0 @@
----
-order: 01
-title: Single Sign-On for Regular Web Apps
-image: /media/articles/architecture-scenarios/web-oidc.png
-extract: Traditional web application which needs to authenticate users using OpenID Connect.
-description: Regular web app scenario which needs to authenticate users using OpenID Connect.
-toc: true
----
-
-# Single Sign-On for Regular Web Apps
-
-In this scenario, we will build a web application for a fictitious company named ExampleCo. The app is meant to be used by ExampleCo's employees and contractors. Employees will use their existing corporate directory (Active Directory), while contractors will be managed in a separate user store.
-
-::: panel TL;DR
-* Auth0 supports open standards such as OAuth 2.0 and OpenID Connect (OIDC) for authentication and authorization (see [Which protocol to use](/architecture-scenarios/application/web-app-sso/part-1#which-protocol-to-use))
-* OIDC supports several different authorization flows - the most appropriate one for Web Applications being the Authorization Code Flow (see [Authentication Flow](/architecture-scenarios/application/web-app-sso/part-1#authentication-flow))
-* Your application will be configured in Auth0 as an application (see [Application](/architecture-scenarios/application/web-app-sso/part-2#application))
-* Identity Providers will be configured in Auth0 as a Connection (see [Connections](/architecture-scenarios/application/web-app-sso/part-2#connections))
-* Auth0 provides a Lock widget, which allow users to log in to the application (see [User Login](/architecture-scenarios/application/web-app-sso/part-3#user-login))
-* The web application needs to manage session state to keep track of the fact that the user is logged in. Along with this, Auth0 and the Identity Provider is also managing session information. (see [Session Management](/architecture-scenarios/application/web-app-sso/part-3#session-management))
-* Conversely, logging a user out also involves three layers of session management (see [User Logout](/architecture-scenarios/application/web-app-sso/part-3#user-logout))
-* Access Control can be managed with the Auth0 Authorization Extension (see [Access Control](/architecture-scenarios/application/web-app-sso/part-3#access-control))
-:::
-
-::: note
-By _Regular Web App_, we mean an app that uses primarily server side, page `GET`, `POST`, and cookies for maintaining state. This is contrast with a Web _SPA_ (Single Page App), that heavily relies on client side JavaScript code calling an API.
-:::
-
-## The Premise
-
-ExampleCo is a consulting startup company. Currently they have approximately 100 employees and they also outsource several activities to external contractors. Most of the employees work from the company's main office, but there are some teams that work remotely. Additionally, some employees frequently travel to customer locations and work from mobile devices.
-
-All employees and external contractors are required to fill in their timesheets every week using spreadsheets. The current system is inefficient and the company decided that they need to move to a better and more automated solution.
-
-The company evaluated several of the available timesheets application and concluded that it would be more cost-effective to build their own in-house solution, since they are looking for a very simple application at the moment. The app will be built using ASP.NET Core, since their developers are already using this technology and they can have the app ready in a week or so.
-
-### Goals & Requirements
-
-ExampleCo wants to launch the new solution quickly so they chose to start simple and build into it as they gather feedback from their employees.
-
-The application should be available to logged in users only. Each user will have a role, and based on this role, they should be able to perform certain actions and view specific data.
-
-::: panel Authentication vs Authorization
-ExampleCo wants to __authenticate__ and __authorize__ each user. Authentication has to do with identity: verifying that the user is indeed who they claim to be. Authorization is about deciding which resources a user should have access to, and what they should be allowed to do with those resources.
-:::
-
-ExampleCo's timesheets app needs to support two roles: _User_ and _Admin_:
-- Someone with the User role can add timesheet entries, by specifying the date, the application and the hours worked. The Admin role also has this same right.
-- Those with the User role should have access only to their own timesheets entries.
-- Someone with the Admin role can additionally:
- - Approve or reject timesheet entries of other users.
- - Edit the application drop-down list of values (add, edit, delete).
-
-Each user will be required to fill in their timesheets by the end of the week. They can either choose to register daily their timesheets or add the entries for the whole week together. The timesheets will have to be reviewed and approved by an Admin. The rejected entries will have to be updated by each employee and re-submitted for approval.
-
-The company uses Active Directory for all employees and employees will sign into the Timesheet application using their Active Directory credentials. The external contractors can sign in with a username and password. Contractors are not on ExampleCo's corporate directory.
-
-ExampleCo wants to minimize user login burden, but wants to maintain a level of security depending on the operation: submitting timesheet entries is lower risk than approving them. However the approved timesheets are used for customer charging so security is definitely a requirement. The authentication strategy should be flexible so it can adapt as the company grows. For example, they should easily be able to add additional authentication requirements, like multifactor authentication, for Admins.
-
-The solution should be available both to the employees with a physical presence in the company office, as well as to those working remotely, without the overhead of a VPN connection, hence the app should be deployed on a cloud provider like Heroku or Microsoft Azure.
-
-
-
-<%= include('./_stepnav', {
- next: ["1. Solution Overview", "/architecture-scenarios/application/web-app-sso/part-1"]
-}) %>
diff --git a/articles/architecture-scenarios/application/web-app-sso/part-1.md b/articles/architecture-scenarios/application/web-app-sso/part-1.md
deleted file mode 100644
index 7671d8390c..0000000000
--- a/articles/architecture-scenarios/application/web-app-sso/part-1.md
+++ /dev/null
@@ -1,94 +0,0 @@
----
-description: Regular web app scenario solution overview
-toc: true
----
-
-# SSO for Regular Web Apps: Solution Overview
-
-In this section, we'll cover the solution we're implementing, including details on identity management, protocols to use, and the authentication flow required.
-
-## Identity Management
-
-ExampleCo decided to use Auth0 as their Identity as a Service (IDaaS) provider. The reasoning behind this decision was that the company did not want to commit resources on training, implementation and maintenance of identity and access management. Furthermore, the company plans on building into this solution in the future, possibly adding a mobile native app and an API to push approved timesheets to their internal systems. Auth0 provides the flexibility to incorporate such changes in their architecture with minimum effort.
-
-::: note
-Identity-as-Service ("IDaaS") is a cloud-based service for identity and access management. The offered services often include SSO, federated identity, password management, and more.
-:::
-
-## Which protocol to use
-
-The next decision has to do with which protocol to use, OAuth 2.0 with OpenID Connect (OIDC) or SAML.
-
-::: note
-Auth0 implements proven, common and popular identity protocols, both for consumer oriented web products (OAuth 2.0, OAuth 1.0, OpenID) and for enterprise deployments (SAML, WS-Federation, LDAP). You have complete freedom to use the one that best meets your business needs.
-:::
-
-__OpenID Connect__ is an authentication protocol, based on the OAuth 2.0 family of specifications. It uses simple JSON identity tokens (JWT) delivered via the OAuth 2.0 protocol.
-
-::: panel OAuth vs OpenID Connect (OIDC)
-OAuth 2.0 and OpenID Connect (OIDC) are often mistaken for the same thing, but this is not exact.
-__OAuth 2.0__ is a protocol that lets you authorize one website (the consumer or application) to access your data from another website (the resource server or provider). For example, you want to authorize a website to access some files from your Dropbox account. The website will redirect you to Dropbox which will ask you whether it should provide access to your files. If you agree the website will be authorized to access your files from Dropbox. At the core, OAuth 2.0 is about resource access and sharing.
-__OpenID Connect__, on the other hand, is a simple identity layer built on top of the OAuth 2.0 protocol. It gives you one login for multiple sites. Each time you need to log in to a website using OIDC, you are redirected to your OpenID site where you login, and then taken back to the website. At the core, OIDC is concerned with user authentication.
-:::
-
-__SAML__ is an XML-based protocol, that provides both authentication and authorization between trusted parties.
-
-Compared to SAML, OpenID Connect is lighter weight and simpler to deal with. SAML is proven, powerful and flexible, but for the requirements of this app, that flexibility and power is not required. Identity federation (one of the most compelling reasons for adopting SAML) is not required here either, And if it ever became a requirement, it can be easily handled by Auth0, in the same way it deals with AD (that uses LDAP).
-
-For these reasons, ExampleCo will use OpenID Connect for their implementation.
-
-## Authentication Flow
-
-OpenID Connect supports more than one flow for authentication. Since our scenario involves a regular web app we will use the __Authorization Code Flow__.
-
-The flow goes as follows:
-1. The web app (called the __Client__ in OIDC terms) initiates the authentication request by redirecting the __user-agent__ (browser) to Auth0 (the __Authorization Server__ in OIDC terms).
-1. Auth0 authenticates the user (via the user-agent). The first time the user goes through this flow a consent page will be shown where the permissions that will be given to the Application are listed (for example, post messages, list contacts). The user logs in to the service (unless they are already logged in) and authorizes the application access.
-1. Assuming the user grants access, Auth0 redirects the __user-agent__ back to the __Application__, along with an _authorization code_ in the querystring.
-1. The Application sends the _authorization code_ to Auth0, along with the application credentials (`client_id` and `client_secret`), and asks for a token.
-1. Auth0 authenticates the __Application__ (using the `client_id` and `client_secret`) and validates the _authorization code_. If valid, Auth0 responds back with an __ID Token__.
-
-
-
-::: panel Form Post Response Mode
-Another option is to use the __OAuth 2.0 Form Post Response Mode__ with `response_type=id_token&response_mode=form_post`. Due to the `response_type=id_token` request parameter, the response contains the `id_token` directly, instead of the authorization code, while the `response_mode=form_post` encodes the `id_token` with the rest of the Authorization Response parameters as HTML form values that are auto-submitted in the User Agent. This way you can have an optimized authentication flow (no need to exchange the code for an `id_token`), however you have to make sure that it is supported by the technology you are using to implement your app (ASP .NET Core middleware does support it). For more details refer to the [OAuth 2.0 Form Post Response Mode specification](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html).
-:::
-
-The __ID Token__ (usually referred to as `id_token`) is a __JSON Web Token (JWT)__ that contains identity data. It is consumed by the application and used to get user information like the user's name, email, and so forth, typically used for UI display.
-
-::: panel More on tokens
-Tokens are alphanumeric strings used in token-based authentication. They allow users to authenticate with a username and password once and get a token in return which they can use from that point on. They have a limited lifetime duration.
-
-__JSON Web Tokens (JWTs)__ are tokens that conform to the [JSON Web Token Standard](https://tools.ietf.org/html/rfc7519) and contain information about an identity in the form of claims. They are self-contained in that it is not necessary for the recipient to call a server to validate the token. JWTs can be signed using a secret (with the __HMAC__ algorithm) or a public/private key pair using __RSA__. You can find more information on JWT [here](/jwt).
-
-The ID Token, which is a JWT, conforms to an industry standard (IETF [RFC 7519](https://tools.ietf.org/html/rfc7519)) and contains three parts: A header, a body and a signature.
-- The header contains the type of token and the hash algorithm used on the contents of the token.
-- The body, also called the payload, contains identity claims about a user. There are some claims with registered names, for things like the issuer of the token, the subject of the token (who the claims are about), and the time of issuance. Any number of additional claims with other names can be added, though care must be taken to keep the JWT within the browser size limitations for URLs.
-- The signature is used by the recipient of a JWT to validate the integrity of the information conveyed in the JWT.
-:::
-
-### How to validate an ID Token
-
-The validation of an ID Token requires several steps:
-1. If the ID Token is encrypted, decrypt it using the keys and algorithms that the Application specified.
-1. The Issuer Identifier for the OpenID Provider must match the value of the `iss` (issuer) claim.
-1. The `aud` (audience) claim should contain the Application's `client_id` value. The ID Token must be rejected if the ID Token does not list the Application as a valid audience, or if it contains additional audiences not trusted by the Application.
-1. If the ID Token contains multiple audiences, the Application should verify that an `azp` claim is present.
-1. If an `azp` (authorized party) claim is present, the Application should verify that its `client_id` is the claim value.
-1. The Application must validate the signature of ID Tokens according to JWS using the algorithm specified in the JWT `alg` header parameter. The Application must use the keys provided by the Issuer.
-1. The `alg` value should be the default of `RS256` or the algorithm sent by the Application in the `id_token_signed_response_alg` parameter during registration.
-1. If the JWT `alg` header parameter uses a MAC based algorithm such as `HS256`, `HS384`, or `HS512`, the octets of the UTF-8 representation of the client_secret corresponding to the `client_id` contained in the `aud` (audience) claim are used as the key to validate the signature. For MAC based algorithms, the behavior is unspecified if the `aud` is multi-valued or if an `azp` value is present that is different than the `aud` value.
-1. The current time must be before the time represented by the `exp` claim.
-1. The `iat` claim can be used to reject tokens that were issued too far away from the current time, limiting the amount of time that nonces need to be stored to prevent attacks. The acceptable range is Application specific.
-1. If a `nonce` value was sent in the Authentication Request, a `nonce` claim must be present and its value checked to verify that it is the same value as the one that was sent in the Authentication Request. The Application should check the `nonce` value for replay attacks. The precise method for detecting replay attacks is Application specific.
-1. If the `acr` claim was requested, the Application should check that the asserted claim value is appropriate.
-1. If the `auth_time` claim was requested, either through a specific request for this claim or by using the `max_age` parameter, the Application should check the `auth_time` claim value and request re-authentication if it determines too much time has elapsed since the last End-User authentication.
-
-::: note
-If you store ID Tokens on your server, you must do so securely.
-:::
-
-<%= include('./_stepnav', {
- prev: ["Introduction", "/architecture-scenarios/application/web-app-sso"],
- next: ["2. Auth0 Configuration", "/architecture-scenarios/application/web-app-sso/part-2"]
-}) %>
diff --git a/articles/architecture-scenarios/application/web-app-sso/part-2.md b/articles/architecture-scenarios/application/web-app-sso/part-2.md
deleted file mode 100644
index dc3f22ffe8..0000000000
--- a/articles/architecture-scenarios/application/web-app-sso/part-2.md
+++ /dev/null
@@ -1,105 +0,0 @@
----
-description: Regular web app scenario configuration for Auth0
-toc: true
----
-# SSO for Regular Web Apps: Auth0 Configuration
-
-In this section we will review all the configurations we need to apply using the [Auth0 Dashboard](${manage_url}).
-
-## Application
-
-The Auth0 configuration part starts with registering the timesheets app at the Auth0 dashboard as an __application__. An application is making protected resource requests on behalf of the resource owner (end-user).
-
-::: note
-The term "application" does not imply any particular implementation characteristics. An application can be a web app, a mobile app or an SPA. In the case of ExampleCo it is a ASP.NET Core web app.
-:::
-
-The main characteristics of an application in Auth0 are:
-- __Name__: The canonical name of the application. This is used to identify the application at the portal, emails, logs, and more.
-- __Client ID__ (read-only): The unique identifier for the application. This is the ID used in the application when setting up authentication with Auth0. It is an auto-generated alphanumeric string.
-- __Client secret__ (read-only): A string used to sign and validate tokens which will be used in the different authentication flows. It is auto-generated and it must be kept confidential.
-- __Domain__: The domain name assigned to the Auth0 account. The format of the domain is `{account-name}.auth0.com` or `{account-name}.{location}.auth0.com`, for example `ExampleCo.auth0.com`.
-- __Callback URL__: The URL where the user is redirected after they authenticate.
-
-### Create an Application
-
-ExampleCo's scenario involves only one application: the timesheets web app. Hence we have to configure one Application at Auth0 side.
-
-To register a database connection, go to the [dashboard](${manage_url}) and in the side navigation select [Applications](${manage_url}/#/applications).
-
-Click on the button __+ Create Application__. You will be prompted for the name and the type of the application. We will name our application `Timesheet-App` and select `Regular Web Applications` as the application type.
-
-
-
-When you click __Create__ you will be navigated to the [Quick Start view](${manage_url}/#/applications/${account.clientId}/quickstart). Here you can pick the technology you plan on using to build your app and the relevant how-to quickstart will be displayed.
-
-The other available views are:
-- [Settings](${manage_url}/#/applications/${account.clientId}/settings): Here you can view and update the settings of your application. This is the page you will use to retrieve information like _Domain_, _Client ID_, and _Client Secret_. In this page you will also have to [set the __Callback URL__ for your application](#configure-callback-urls).
-- [Addons](${manage_url}/#/applications/${account.clientId}/addons): Addons are plugins associated with an application in Auth0. Usually, they are third party APIs used by the application that Auth0 generates Access Tokens for (for example Salesforce, Azure Service Bus, Azure Mobile Services, SAP, and so forth). We will not use any Addons in this scenario.
-- [Connections](${manage_url}/#/applications/${account.clientId}/connections): Connections are sources of users. We will use this view shortly to enable specific connections for our application.
-
-### Configure Callback URLs
-
-The __Allowed Callback URLs__ field contains the URL(s) where Auth0 will redirect to after the user has authenticated in order for the OpenID Connect to complete the authentication process. You can specify multiple valid URLs by comma-separating them. You can use the star symbol as a wildcard for subdomains, for example `*.google.com`. Make sure to specify the protocol, `http://` or `https://`, otherwise the callback may fail in some cases.
-
-The Callback URL for our sample project is `http://localhost:5000/signin-auth0`. Go ahead and set this value to the __Allowed Callback URLs__ field if you plan on using our sample, otherwise add the URL you chose to deploy your application to.
-
-## Connections
-
-The next step is to configure the identity providers that will be used for authentication at the web app. Each identity provides maps to a __connection__ in Auth0. Each application needs at least one connection, and each connection can be used for more than one application.
-
-ExampleCo needs to configure two connections: one Active Directory connection for the internal employees, and one Database connection for external parties.
-
-::: panel Supported identity providers
-Auth0 supports a vast variety of protocols and identity providers:
-- Social: Allow your users to log in using Google, Facebook, LinkedIn, Github, and many more.
-- Enterprise: Allow your users to log in using Active Directory, ADFS, LDAP, SAML-P, and many more.
-- Database connections: Create your own user store by configuring a new database connection, and authenticate your users using email/username and password. The credentials can be securely stored either in the Auth0 user store, or in your own database.
-- Passwordless authentication: Allow your users to login without the need to remember a password and use an authentication channel like SMS or e-mail.
-:::
-
-### Create a database connection
-
-To register a database connection, go to the [dashboard](${manage_url}) and in the side navigation select [Connections > Database](${manage_url}/#/connections/database).
-
-Click on the button __+ Create DB Connection__. You will be prompted for the name of the connection. We will name our connection `Timesheet-Users`.
-
-
-
-When you click __Save__ you will be navigated to the _Settings_ page for the new connection. Ensure that you enable your application to use this connection at the _Applications Using This Connection_ section.
-
-
-
-For more information on database connections refer to [Database Identity Providers](/connections/database).
-
-### Create an Active Directory / LDAP Connection
-
-Next you need to configure your Active Directory / LDAP connection. Go to the [Auth0 dashboard](${manage_url}) and in the side navigation select the [Connections > Enterprise](${manage_url}/#/connections/enterprise)).
-
-There you need to create the AD / LDAP connection and install the AD Connector. You can find details in these documents:
-- [How to connect your Active Directory with Auth0](/connections/enterprise/active-directory)
-- [How to install the Active Directory/LDAP Connector](/connector)
-
-::: note
-The AD/LDAP Connector, is a bridge between your Active Directory and the Auth0 Service. This bridge is necessary because AD is typically locked down to your internal network, and Auth0 is a cloud service running on a completely different context.
-[More information](/connector/overview)
-:::
-
-Once you have configured the connection and the connector, be sure to enable your application to use this AD / LDAP connection:
-
-
-
-::: panel Kerberos support
-The AD/LDAP connector supports Kerberos to make it easer for your users to authenticate when they are on a domain-joined machine within the corporate network. To activate Kerberos on an Active Directory you have to simply enable the option in the dashboard. After enabling Kerberos you'll also be able to configure the __IP Ranges__. When users originate from these IP address ranges this information will be exposed in the SSO endpoint which means client-side SDKs like auth0.js and the Lock will be able to detect Kerberos support and allow Integrated Windows Authentication.
-[More information](/connector/kerberos)
-
-::: note
-If you enable Kerberos then you need to make some changes to the AD/LDAP's configuration file. For details refer to: [Modify the AD/LDAP Connector Settings](/connector/modify).
-:::
-
-Now that we have designed our solution and discussed the configurations needed on Auth0 side, we can proceed with integrating Auth0 with our timesheets web app. That's what the next paragraph is all about, so keep reading!
-
-<%= include('./_stepnav', {
- prev: ["1. Solution Overview", "/architecture-scenarios/application/web-app-sso/part-1"],
- next: ["3. Application Implementation", "/architecture-scenarios/application/web-app-sso/part-3"]
-}) %>
diff --git a/articles/architecture-scenarios/application/web-app-sso/part-3.md b/articles/architecture-scenarios/application/web-app-sso/part-3.md
deleted file mode 100644
index 52afc1b4f7..0000000000
--- a/articles/architecture-scenarios/application/web-app-sso/part-3.md
+++ /dev/null
@@ -1,171 +0,0 @@
----
-description: Regular web app scenario application implementation
-toc: true
----
-# SSO for Regular Web Apps: Application Implementation
-
-Let's walk through the implementation of our regular web application. We used ASP .NET Core for the implementation, you can find the code in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-webapp-oidc).
-
-The sample contains an application which uses Active Directory integration to authenticate company employees and an Auth0 database connection for external contractors. Authorization is implemented using rules and claims as we will see in detail in this paragraph.
-
-## User Login
-
-Auth0 provides a Lock widget which serves as a login component for your application, meaning that you do not have to implement your own login screen. The Lock widget seamlessly integrates with all of the connections you configure inside your Auth0 dashboard, whether they be database, social or enterprise connections.
-
-There are a number of different ways in which you can implement a Login screen using a web application and Auth0:
-- __Hosted Lock__: Use an instance of the Lock widget which is hosted on the Auth0 infrastructure.
-- __Embedded Lock__: Embed the Lock widget inside a web page of your application. You have some customization options for the actual Lock widget, and full control over the rest of the HTML on the page.
-- __Custom UI__: Develop a completely custom web page for the login screen. The custom HTML form will post back to your server which will in turn authenticate the user using the Authentication API. For more information on when to use a Custom UI refer to [Lock vs. a Custom UI](/libraries/when-to-use-lock).
-
-The recommended best practice is to use Hosted Lock because it is the most secure option and the easiest way to enable users to log in to your application.
-
-### Automate Home Realm Discovery (HRD)
-
-By default, Lock will display all the connections available for login. Selecting the appropriate Identity Providers from multiple options is called _Home Realm Discovery (HRD)_. In our case the options are either authenticating with Active Directory (for company employees) or using email/password for our database connection (external contractors).
-
-You may however want to avoid that first step, where the user needs to choose the Identity Provider (IdP), and have the system identify it instead of asking every time. Lock offers you the following options:
-
-- __Identify the IdP programatically__: When you initiate an authentication transaction with Auth0 you can optionally send a `connection` parameter. This value maps directly with any connection defined in your dashboard. When using the Hosted version of Lock by calling the [`/authorize`](/api/authentication/reference#database-ad-ldap-passive-) endpoint, you can pass along a `connection` query string parameter containing the name of the connection. Alternatively, if you are using Embedded Lock, this is as simple as writing `auth0.show({connections: ['YOUR_CONNECTION']});`.
-
- There are multiple practical ways of getting the `connection` value. One of them is to use __vanity URLs__: for example, company employees will use `https://internal.yoursite.com`, while external contractors will use `https://external.yoursite.com`.
-
-- __Use email domains__: Lock can use email domains as a way of routing authentication requests. Enterprise connections in Auth0 can be mapped to `domains`. If a connection has this setup, then the password textbox gets disabled automatically when typing an e-mail with a mapped domain. Note that you can associate multiple domains to a single connection.
-
-For additional information on this topic refer to: [Selecting the connection in Auth0 for multiple login options](/libraries/lock/v10/selecting-the-connection-for-multiple-logins).
-
-## Session Management
-
-When talking about managing sessions, there are typically three layers of sessions we need to consider:
-
-- __Application Session__: The first is the session inside the application. Even though your application uses Auth0 to authenticate users, you will still need to keep track of the fact that the user has logged in to your application. In a normal web application this is achieved by storing information inside a cookie.
-- __Auth0 session__: Next, Auth0 will also keep a session and store the user's information inside a cookie. Next time when a user is redirected to the Auth0 Lock screen, the user's information will be remembered.
-- __Identity Provider session__: The last layer is the Identity Provider, for example Facebook or Google. When you allow users to sign in with any of these providers, and they are already signed into the provider, they will not be prompted to sign in. They may simply be required to give permissions to share their information with Auth0 and in turn your application.
-
-When developing a web application, you will therefore need to keep track of the fact that the user has logged in to your Web application. You can do this by making use of a cookie-based session to keep track of the fact that the user has signed in, and also store any of the user related information or tokens.
-
-::: panel How do I control the duration of the user's local application session? Can I drive that from Auth0?
-The web app has full control over the user's local application session. How this is done usually depends on the web stack being used (for example, ASP.NET). Regardless, all approaches ultimately use one or more cookies to control the session. The developer can choose to use the expiration of the JWT `id_token` returned by Auth0 to control their session duration or ignore it completely. Some developers store the `id_token` itself in session state and end the user's session when it has expired.
-
-The reason why you would use the expiration of the token to determine the expiration of the local session is because it gives you centralized control of the duration of a user session from the Auth0 Dashboard.
-:::
-
-The login flow is as follows:
-
-
-
-1. __Initiate OIDC Authentication Flow__: The user's browser will send a request to Auth0 to initiate the OIDC flow.
-1. __Set SSO Cookie__: Auth0 will set a cookie to store the user's information.
-1. __Code exchange and return ID Token__: Auth0 will make a request back to the web server and return the code. The web server will exchange the code for an ID Token.
-1. __Set auth cookie and send response__: The web server will send a response back to the browser and set the application authentication cookie to store the user's session information.
-1. __Auth cookie sent with every subsequent request__: The application authentication cookie will be sent on every subsequent request as proof that the user is authenticated.
-
-::: panel How does Auth0's SSO session impact the application's session?
-Auth0 manages its own single-sign-on session. Applications can choose to honor or ignore that SSO session when it comes to maintaining their own local session. The Lock widget even has a special feature where it can detect if an Auth0 SSO session exists and ask the user if they wish to log in again as that same user.
-
-
-
-If they do so, they are signed in without having to re-enter their credentials with the actual IDP. Even though the user didn't authenticate, the application still performs an authentication flow with Auth0 and obtains a new `id_token`, which can be used to then manage the new local application session.
-:::
-
-**See the implementation in [ASP.NET Core](/architecture-scenarios/application/web-app-sso/implementation-aspnetcore#configure-the-cookie-and-oidc-middleware)**.
-
-## User Logout
-
-When logging the user out, you will once again need to think about the three layers of sessions which we spoke about before:
-- __Application Session__: You need to log out the user from your Web Application, by clearing their session.
-- __Auth0 session__: You need to log out the user from Auth0. To do this you redirect the user to `https://${account.namespace}/v2/logout`. Redirecting the user to this URL clears all single sign-on cookies set by Auth0 for the user.
-- __Identity Provider session__: Although this is not common practice, you can force the user to log out from the Identity Provider used, for example Facebook or Google. To do this add a `federated` querystring parameter to the logout URL: `https://${account.namespace}/v2/logout?federated`.
-
-To redirect a user after logout, add a `returnTo` querystring parameter with the target URL as the value: `https://${account.namespace}/v2/logout?returnTo=http://www.example.com`. Note, that you will need to add the `returnTo` URL as an __Allowed Logout URLs__. For more information on how to implement this refer to: [Logout](/logout).
-
-The logout flow (not including federated logout) is as follows:
-
-
-
-1. __Initiate Logout Flow__: The logout flow will be initiated from the browser, for example by the user clicking a _Logout_ link. A request will be made to the web server.
-1. __Clear user’s local session__: The user's Application Session / Cookie will be cleared.
-1. __Redirect browser to Auth0 Logout__: The user's browser will be redirected to the Auth0 Logout URL.
-1. __Clear SSO Cookie__: Auth0 will clear the user's SSO Cookie.
-1. __Redirect to post-logout URL__: Auth0 will return a redirect response and redirect the user's browser to the `returnTo` querystring parameter.
-
-**See the implementation in [ASP.NET Core](/architecture-scenarios/application/web-app-sso/implementation-aspnetcore#implement-the-logout)**.
-
-## Access Control
-
-Authorization refers to the process of determining what actions a user can perform inside your application.
-
-You can either implement authorization directly inside your application, independently of Auth0, or use one of the available ways to retrieve the user authorization levels, put them as authorization claims inside the `id_token` and validate these claims inside your application, once you retrieve the token, to control access.
-
-There are various ways in which you can retrieve and set the user authorization claims when using Auth0:
-- By configuring and using the [Auth0 Authorization Extension](/extensions/authorization-extension).
-- By using Active Directory groups. These can be used in combination with the Authorization Extension by mapping Active Directory Groups to Groups you define using the Authorization extension.
-- Add metadata to the user's profile by making use of [rules](/rules#add-roles-to-a-user).
-- By calling an external services from inside a [rule](/rules).
-
-Since in our case the company has already Active Directory set up, we will enforce access control using the Authorization Extension in combination with Active Directory groups.
-
-::: panel Authorization Extension
-At this point in time the authorization extension is primarily designed to enforce coarse-grained authorization, for example to control access to an application based on a user's group membership. It is not necessarily designed to control fine-grained access (such as whether a user can perform a specific action inside the application), even though this is how we are utilizing it in this instance.
-:::
-
-All users will implicitly be regular users, but timesheet administrators will be assigned to an `Admin` group which will allow them to approve timesheets. The Authorization Extension allows for mapping groups to existing group membership.
-
-All timesheet administrators will be assigned to the `Timesheet Administrators` group on Active Directory, which will be automatically mapped to the `Admin` group inside the Timesheet Application.
-
-When you install the Authorization Extension, it creates a rule in the background, which does the following:
-1. Determine the user's group membership.
-1. Store the user's group membership info as part of the `app_metadata`.
-1. Add the user's group membership to the outgoing token.
-1. Verify that the user has been granted access to the current application.
-
-
-### Install the Authorization Extension
-
-To install the Authorization extension navigate to the [Extensions](${manage_url}/#/extensions) view of your Auth0 Dashboard, and select and install the Auth0 Authorization extension.
-
-
-
-Once installed, you will see the app listed under _Installed Extensions_.
-
-When you click on the link to open the extension for the first time, you will be prompted to provide permission for the extension to access your Auth0 account. If you do so, you will be redirected to the Authorization Dashboard.
-
-Once on the Authorization Dashboard, navigate to Groups in the navigation menu, and create a new group called `Admin`.
-
-
-
-After the group has been added you can click on the new group to go to the group management section. Go to the _Group Mappings_ tab and add a new group mapping which will map all Active Directory users in the `Timesheet Admins` groups to the `Admin` group you just created.
-
-
-
-Once you click __Save__ you can see the new mapping listed.
-
-
-
-With the mapping configured you only need to maintain membership to the `Timesheet Admins` group in Active Directory, and those users will be automatically mapped to the `Admin` group inside our application.
-
-For more information refer to the [Authorization Extension documentation](/extensions/authorization-extension).
-
-### Enforce permissions in your application
-
-When you installed the Authorization Extension, it also created an Auth0 rule which will add an `authorization` claim with all the authorization related settings for a particular user. The groups for a user will be added as a sub-claim of the `authorization` claim called `groups` and all the groups a user belongs to will be added as an array to this claim. This is an example of what JSON payload of a ID Token may look like with the groups listed:
-
-```json
-{
- "sub": "1234567890",
- "name": "John Doe",
- "authorization": {
- "groups": ["Admin"]
- }
-}
-```
-
-In your application you will therefore need to decode the ID Token returned when a user is authenticated, and extract the groups which a user belongs to from the `authorization` claim. You can then store these groups, along with other user information inside the user's session, and subsequently query these to determine whether a user has permissions to perform a certain action based on their group membership.
-
-::: note
-See the implementation in [ASP.NET Core](/architecture-scenarios/application/web-app-sso/implementation-aspnetcore#implement-admin-permissions).
-:::
-
-<%= include('./_stepnav', {
- prev: ["2. Auth0 Configuration", "/architecture-scenarios/application/web-app-sso/part-2"],
- next: ["4. Conclusion", "/architecture-scenarios/application/web-app-sso/part-4"]
-}) %>
diff --git a/articles/architecture-scenarios/application/web-app-sso/part-4.md b/articles/architecture-scenarios/application/web-app-sso/part-4.md
deleted file mode 100644
index b3c4be4d57..0000000000
--- a/articles/architecture-scenarios/application/web-app-sso/part-4.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-description: Regular web app scenario conclusion
-toc: true
----
-# SSO for Regular Web Apps: Conclusion
-
-In this tutorial we covered a simple scenario: a regular web app, hosted in the cloud, using Auth0 for authentication, while utilizing the existing Active Directory user store. We learned what OpenID Connect offers and why it was preferable for this business case, how the Authentication Flow works, what an ID Token is and how to validate and manipulate it, how to configure applications and connections on Auth0 dashboard, how to implement user login and logout using Lock, and how session management and access control works.
-
-We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
-
-We used ASP .NET Core for the sample web app implementation, hopefully though after going through this document you are able to build such a web app using the framework you prefer.
-
-<%= include('./_stepnav', {
- prev: ["3. Application Implementation", "/architecture-scenarios/application/web-app-sso/part-3"]
-}) %>
diff --git a/articles/architecture-scenarios/application/web-saml.md b/articles/architecture-scenarios/application/web-saml.md
deleted file mode 100644
index bfab970284..0000000000
--- a/articles/architecture-scenarios/application/web-saml.md
+++ /dev/null
@@ -1,29 +0,0 @@
----
-order: 05
-title: Regular Web App (using SAML)
-image: /media/articles/architecture-scenarios/web-saml.png
-extract: Traditional web application which needs to authenticate users using SAML2
-description: Explains the architecture scenario of using a traditional web application to authenticate users using SAML2.
-beta: true
----
-
-# Regular Web App (using SAML)
-
-::: note
-This architecture scenario is under construction and will be updated soon.
-:::
-
-
-
-In this scenario you have a traditional web application which needs to authenticate users using SAML2. The end result of the SAML flow after a user has successfully authenticated is a POST of the SAML Response (which contains SAML Assertions about the user) to a server-side endpoint (aka callback) in the Application. The Application therefore needs some SAML library that can process that response, validate the user, and create a local login session, which usually stored using one or more cookies.
-
-::: note
-In this scenario an Access Token is also returned but it is rarely used since their is no API involved against which the user needs to be authenticated.
-:::
-
-## Read More
-
-The following is a list of articles on this website which will help you to implement this scenario:
-
-* [Lock](/libraries/lock)
-* [SAML](/saml-configuration)
diff --git a/articles/architecture-scenarios/b2b-b2e.md b/articles/architecture-scenarios/b2b-b2e.md
new file mode 100644
index 0000000000..590a1cea72
--- /dev/null
+++ b/articles/architecture-scenarios/b2b-b2e.md
@@ -0,0 +1,44 @@
+---
+order: 07
+title: Business to Business + Employees Identity Scenarios
+image: /media/articles/architecture-scenarios/b2b-b2e.png
+extract: This is essentially a hybrid between B2B and B2E where you have a larger SAAS application, like Zendesk for example, where users are grouped into companies.
+description: Explains the architecture scenario of a hybrid between B2B and B2E where you have a larger SAAS application.
+beta: true
+topics:
+ - b2b
+ - b2e
+ - architecture
+ - lockjs
+ - saml
+ - active-directory
+ - social-connections
+contentType: concept
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Business to Business + Employees Identity Scenarios
+
+::: note
+This architecture scenario is under construction and will be updated soon.
+:::
+
+
+
+This is essentially a hybrid between B2B and B2E for larger SAAS applications (such as Zendesk). In a situation like this, users would primarily be grouped into companies, but you may also have internal users (employees) who log into perform support or administrative tasks. Those internal users will typically use federated identity to authenticate.
+
+## Read More
+
+The following is a list of articles on this website which will help you to implement this scenario:
+
+* [Lock](https://auth0.com/lock)
+* [Protocols supported by Auth0](/protocols)
+* [Connect Active Directory with Auth0](/connections/enterprise/active-directory-ldap)
+* [SAML](/saml-configuration)
+* [Using Auth0 in SaaS, multi-tenant Apps](/saas-apps)
+* [Identity Providers supported by Auth0](/identityproviders)
+* [Social Login](https://auth0.com/learn/social-login/)
+* [Auth0 SSO Dashboard (sample)](https://github.com/auth0-samples/auth0-sso-dashboard)
diff --git a/articles/architecture-scenarios/b2b.md b/articles/architecture-scenarios/b2b.md
new file mode 100644
index 0000000000..ec33e404f6
--- /dev/null
+++ b/articles/architecture-scenarios/b2b.md
@@ -0,0 +1,52 @@
+---
+url: /architecture-scenarios/b2b
+classes: topic-page
+title: Business to Business Identity and Access Management
+description: Explains the architecture scenario B2B IAM with a SAAS application.
+topics:
+ - b2b
+ - b2biam
+ - SDLC
+contentType: index
+useCase:
+ - implementation
+---
+
+
+
+
Business to Business Identity and Access Management
+
+ This guidance is relevant to all project stakeholders. We recommend reading it in its entirety at least once, even if you've already started your journey with Auth0. We provide a Project Planning Guide in PDF format, details about how to get started with each phase of the implementation process, and checklists to help you manage the tasks in each phase.
+
Business to Consumer Identity and Access Management
+
+ This guidance is relevant to all project stakeholders. We recommend reading it in its entirety at least once, even if you've already started your journey with Auth0. We provide a Project Planning Guide in PDF format, details about how to get started with each phase of the implementation process, and checklists to help you manage the tasks in each phase.
+
+
+
+<%= include('./_includes/_base-ways-to-integrate.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('./_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Get started
+
+<%= include('./_includes/_base-intro.md', { platform: 'b2c' }) %>
+
+<%= include('../_includes/_topic-links', { links: [
+ 'architecture-scenarios/implementation/b2c/b2c-architecture',
+ 'architecture-scenarios/implementation/b2c/b2c-provisioning',
+ 'architecture-scenarios/implementation/b2c/b2c-authentication',
+ 'architecture-scenarios/implementation/b2c/b2c-branding',
+ 'architecture-scenarios/implementation/b2c/b2c-deployment',
+ 'architecture-scenarios/implementation/b2c/b2c-qa',
+ 'architecture-scenarios/implementation/b2c/b2c-profile-mgmt',
+ 'architecture-scenarios/implementation/b2c/b2c-authorization',
+ 'architecture-scenarios/implementation/b2c/b2c-logout',
+ 'architecture-scenarios/implementation/b2c/b2c-operations',
+ 'architecture-scenarios/implementation/b2c/b2c-launch'
+] }) %>
+
+## Implementation planning checklists
+
+<%= include('./_includes/_implementation-checklists.md') %>
diff --git a/articles/architecture-scenarios/b2e.md b/articles/architecture-scenarios/b2e.md
new file mode 100644
index 0000000000..a35f10a932
--- /dev/null
+++ b/articles/architecture-scenarios/b2e.md
@@ -0,0 +1,114 @@
+---
+order: 06
+title: Business to Employees Identity Scenarios
+image: /media/articles/architecture-scenarios/b2e.png
+extract: Large organization who wants to federate their existing enterprise directory service to allow employees to log in to applications using their existing enterprise credentials.
+description: Explains the architecture scenario of B2E with a large organization that wants to extend their existing enterprise directory service.
+topics:
+ - b2e
+ - architecture
+ - lockjs
+ - active-directory
+ - saml
+ - sso
+contentType: concept
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Business to Employees Identity Scenarios
+
+The B2E (Business to Employees) scenario involves applications that are used by employee users. These are applications that are targeted toward users who are typically acting on behalf of an organization such as an employer, a university, or a group in which they are a member, as opposed to acting on their own behalf.
+
+Such applications that are custom written by the organization may use the OIDC/OAuth protocol to externalize authentication whereas those that have been purchased will often use the SAML protocol. In either case, the enterprise will typically want to use some form of Enterprise connection, such as a SAML Identity Provider, ADFS, G Suite, Azure AD or a directory service such as AD or OpenLDAP, and less frequently, a custom DB, for authentication of enterprise users.
+
+For a business that is creating or integrating applications with Auth0 for a B2E environment, there are several requirements that are common for this scenario. This guide will summarize the most common requirements for B2E applications and explain the Auth0 features which help meet each need.
+
+## Enterprise providers
+
+Most businesses already have a corporate identity repository which has information on all the employee users and user profile information. It may also contain information on partners and contractors. A common requirement for the B2E scenario therefore, is to allow such users to log in via [Auth0 Enterprise connections](/connections/identity-providers-enterprise) such as SAML2 providers, ADFS, G Suite, Azure AD or an on-premise corporate directory service. This is attractive to users because it allows them to avoid creating yet another username and password for each application and instead leverage the same login credential across all their enterprise applications.
+
+This is especially attractive to security interests within the company because user credentials are only exposed to the identity stack instead of to each application. Furthermore, this architecture allows the business to retain control over access to applications because the enterprise identity provider provides a single shutoff point. If a user leaves the organization, administrators can simply disable the user’s account in the corporate identity provider and the user can no longer log in to any of the applications using that identity provider.
+
+Auth0 makes it easy to enable login via a wide variety of enterprise providers with just a few simple configuration steps.
+
+## Groups and roles
+
+With a lot of users, you may set up groups and roles to manage access and privileges. Often, these are stored and administered in a directory service.
+
+Auth0 can get user attributes, like groups and roles, from a directory service or enterprise identity provider during authentication. You can then make the attributes available through tokens returned to the application or with the Auth0 Management API.
+
+## Profile translation
+
+Sometimes a directory or identity provider returns attributes in one format, but your application uses another format. Using Auth0's [Rules](/rules/current/metadata-in-rules), you can [map and translate user profile attributes](https://auth0.com/rules/saml-attribute-mapping). You can even translate between OIDC/OAuth, SAML, WS-Fed, and LDAP.
+
+For example, you retrieve attributes in SAML assertion format from a SAML Identity Provider. With a rule you can then translate the attributes to custom claims in an ID Token for an OIDC/OAuth application.
+
+You can also map SAML attributes to the Auth0 user profile from the dashboard. To do this, go to [Connections > Enterprise > SAMLP Identity Provider](${manage_url}/#/connections/enterprise), select your SAML connection, and set your attribute mappings in the **Mappings** tab.
+
+## Extensibility with augmented user profiles
+
+You may want to enrich user profiles with attributes or data retrieved from other services. For example, you might receive an address or phone number and wish to translate that into a geographic region. [Auth0 Rules](/rules) enable you to write small snippets of code that execute during the authentication transaction. This lets you execute logic or call other services for user information, then add [user metadata](/users/concepts/overview-user-metadata) to the Auth0 user profile and optionally the resulting tokens sent to your applications.
+
+## Single Sign-on
+
+If you have several internal applications, you can set up [Single Sign-on (SSO)](/sso) across them so users only have to log in once.
+
+Auth0 supports integration with applications that externalize authentication using industry standard identity protocols:
+
+* OIDC/OAuth
+* SAML2
+* WS-Fed
+
+After some configuration, all your applications can leverage your enterprise identity provider. In this setup, Auth0 is the broker between your applications and enterprise identity providers.
+
+Now when a user signs in to one application, they can access other applications integrated with Auth0 without having to log in again. This will be true until their SSO session expires. You should configure the SSO session length within Auth0 to meet security policies.
+
+## Single Sign-on integrations
+
+You can also integrate purchased applications with Auth0 for Single Sign-on (SSO). Auth0 provides [pre-built integrations](/integrations/sso) for applications such as:
+
+* Salesforce
+* Zendesk
+* Slack
+* New Relic
+
+## Branding
+
+Branding is an important part of any application. Your logo, colors and styles should be consistent in all parts of the application. You can [customize](/libraries/custom-signup) the login, signup, and error pages displayed by Auth0 so it matches your application. Add your own logo, text, and colors. There's also I18N/L10N support for global rollouts. [Emails for verification or password resets](/email/templates) are customizable too.
+
+[Login screens](/libraries/lock/v11/ui-customization) should appear to come from your application’s branded domain name. To maintain consistency, you can define a [custom domain name](/custom-domains) for the login screen displayed by Auth0.
+
+## Multi-factor authentication
+
+Internal or employee applications often deal with sensitive content. [Multi-factor authentication (MFA)](/mfa) helps protect your data and applications. Auth0 provides a variety of ways to implement MFA. And for more flexibility, you can use Rules to turn it on only for the applications or user groups that need it.
+
+## Logs export
+
+Need to analyze logs or store them long-term? Auth0 provides extensions to [export logs to external tools](/logs) for analysis and retention. You can also retrieve log data with the Management API.
+
+## Audit
+
+Companies have many uses for logs data, one of which is audit reports. Auth0 captures a variety of data in log files, which may be useful for your audit reporting. The logs have information on authenticated users, the identity provider used, and when significant administrative changes are made in the Auth0 dashboard.
+
+Log events each have an event type. You can use event types as filters when querying log data with the Management API, or when exporting logs to log analysis tools.
+
+## Monitoring
+
+Monitoring the infrastructure and services that your applications depend on is critical. Auth0 provides an [Auth0 Status](https://status.auth0.com) page you can subscribe to.
+
+Auth0 makes every effort to minimize outages, but if there is any disruption to service, it will appear on the status page. To support requirements for root cause analysis documentation after a disruption, Auth0 conducts internal analysis and publishes the results on the disruption notice when the analysis is completed.
+
+## Anomaly Detection
+
+An unfortunate part of modern life on the internet is hackers. Hackers are constantly trying to find a way into applications. For example, they may try to log in using common passwords. Or they may use credentials stolen from elsewhere, hoping that users re-used the same passwords at other sites.
+
+Auth0's [Attack Protection](/attack-protection) detects these situations for Auth0 Database connections and provides options for how to respond. Turn on Attack Protection and configure the response options so you can respond appropriately if such an event occurs.
+
+## Github Deployment
+
+Do you manage a lot of your application code in Github? You can deploy code for rules, hooks, or custom database access from there with Auth0's [Github Deployment extension](/extensions/github-deploy).
+
+If you have a full continuous integration/continuous deployment pipeline, use the [Auth0 Deploy CLI tool](https://github.com/auth0/auth0-deploy-cli) for greater flexibility.
diff --git a/articles/architecture-scenarios/business/b2b-b2e.md b/articles/architecture-scenarios/business/b2b-b2e.md
deleted file mode 100644
index 7465dc745b..0000000000
--- a/articles/architecture-scenarios/business/b2b-b2e.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-order: 07
-title: Business to Business + Enterprise Identity Scenarios
-image: /media/articles/architecture-scenarios/b2b-b2e.png
-extract: This is essentially a hybrid between B2B and B2E where you have a larger SAAS application, like Zendesk for example, where users are grouped into companies.
-description: Explains the architecture scenario of a hybrid between B2B and B2E where you have a larger SAAS application.
-beta: true
----
-
-# Business to Business + Enterprise Identity Scenarios
-
-::: note
-This architecture scenario is under construction and will be updated soon.
-:::
-
-
-
-This is essentially a hybrid between B2B and B2E for larger SAAS applications (such as Zendesk). In a situation like this, users would primarily be grouped into companies, but you may also have internal users (employees) who log into perform support or administrative tasks. Those internal users will typically use federated identity to authenticate.
-
-## Read More
-
-The following is a list of articles on this website which will help you to implement this scenario:
-
-* [Lock](https://auth0.com/lock)
-* [Protocols supported by Auth0](/protocols)
-* [Connect Active Directory with Auth0](/connections/enterprise/active-directory)
-* [SAML](/saml-configuration)
-* [Using Auth0 in SaaS, multi-tenant Apps](/saas-apps)
-* [Identity Providers supported by Auth0](/identityproviders)
-* [Social Login](https://auth0.com/learn/social-login/)
-* [Auth0 SSO Dashboard (sample)](https://github.com/auth0-samples/auth0-sso-dashboard)
diff --git a/articles/architecture-scenarios/business/b2b.md b/articles/architecture-scenarios/business/b2b.md
deleted file mode 100644
index 11bf1641ee..0000000000
--- a/articles/architecture-scenarios/business/b2b.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-order: 05
-title: Business to Business Identity Scenarios
-image: /media/articles/architecture-scenarios/b2b.png
-extract: In this scenario you usually have a larger SAAS application, like Zendesk for example, where their customers are typically other companies which are registered as tenants.
-description: Explains the architecture scenario of B2B with large SAAS application.
-beta: true
----
-
-# Business to Business Identity Scenarios
-
-::: note
-This architecture scenario is under construction and will be updated soon.
-:::
-
-
-
-In this scenario you usually have a larger SAAS application, like Zendesk for example, where their customers are typically other companies which are registered as tenants. Each of these companies (also referred to as tenants) will have their own set of users who can access the information of that tenant on the SAAS application.
-
-When a tenant is smaller, these users can be stored and authenticated with a Database connection (username/password). Some of the tenants may also be large enterprise companies who wants federate their enterprise directory so they can manage their own users and the users can log in with their existing enterprise credentials.
-
-## Read More
-
-The following is a list of articles on this website which will help you to implement this scenario:
-
-* [Lock](https://auth0.com/lock)
-* [Protocols supported by Auth0](/protocols)
-* [Using Auth0 in SaaS, multi-tenant Apps](/saas-apps)
-* [Identity Providers supported by Auth0](/identityproviders)
-* [Connect Active Directory with Auth0](/connections/enterprise/active-directory)
-* [Social Login](https://auth0.com/learn/social-login/)
diff --git a/articles/architecture-scenarios/business/b2c.md b/articles/architecture-scenarios/business/b2c.md
deleted file mode 100644
index 17f31735d7..0000000000
--- a/articles/architecture-scenarios/business/b2c.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-order: 04
-title: Business to Consumer Identity Scenarios
-image: /media/articles/architecture-scenarios/b2c.png
-extract: Usually eCommerce or SAAS applications which have end users (consumers) as customers and the application typically used OpenID Connect as a protocol to communicate with Auth0.
-description: Explains the architecture scenario B2C with an eCommerce or SAAS application.
-beta: true
----
-
-# Business to Consumer Identity Scenarios
-
-::: note
-This architecture scenario is under construction and will be updated soon.
-:::
-
-
-
-Usually eCommerce or SAAS applications which have end users (consumers) as customers and the application typically used OpenID Connect as a protocol to communicate with Auth0.
-
-Users are created and stored with a Database connection (username/password) which they can then later use to log in, or alternatively users can use a social connection such as Facebook, Twitter, Google, and so on to log in. Passwordless connections are also common with B2C.
-
-## Read More
-
-The following is a list of articles on this website which will help you to implement this scenario:
-
-* [Lock](https://auth0.com/lock)
-* [Protocols supported by Auth0](/protocols)
-* [Database Identity Providers](/connections/database)
-* [Import users to Auth0](/connections/database/migrating)
-* [Social Login](https://auth0.com/learn/social-login/)
-* [Passwordless](/connections/passwordless)
diff --git a/articles/architecture-scenarios/business/b2e.md b/articles/architecture-scenarios/business/b2e.md
deleted file mode 100644
index b66f66c4c7..0000000000
--- a/articles/architecture-scenarios/business/b2e.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-order: 06
-title: Business to Enterprise Identity Scenarios
-image: /media/articles/architecture-scenarios/b2e.png
-extract: Large organization who wants to federate their existing enterprise directory service to allow employees to log in to applications using their existing enterprise credentials.
-description: Explains the architecture scenario of B2E with a large organization that wants to extend their existing enterprise directory service.
-beta: true
----
-
-# Business to Enterprise Identity Scenarios
-
-::: note
-This architecture scenario is under construction and will be updated soon.
-:::
-
-
-
-In this scenario you have a large organization who wants to federate their existing enterprise directory service to allow employees to log in to the various internal, as well as 3rd party applications, using their existing enterprise credentials.
-
-The 3rd party applications will typically be configured to use SAML as a protocol to communicate with Auth0, whereas the internal applications will more typically use OpenID Connect to communicate with Auth0.
-
-Since there are usually multiple configured applications, SSO (single sign-on) is important. Often times some sort of dashboard UI is used to host shortcuts to all the applications that a given user has access to. In that case, users typically first log into the dashboard and then jump to the various applications they wish to use, and each jump uses SSO to facilitate automatic login.
-
-## Read More
-
-The following is a list of articles on this website which will help you to implement this scenario:
-
-* [Lock](https://auth0.com/lock)
-* [Protocols supported by Auth0](/protocols)
-* [Connect Active Directory with Auth0](/connections/enterprise/active-directory)
-* [SAML](/saml-configuration)
-* [What is SSO (Single Sign On)?](/sso)
-* [Auth0 SSO Dashboard (sample)](https://github.com/auth0-samples/auth0-sso-dashboard)
diff --git a/articles/architecture-scenarios/checklists.md b/articles/architecture-scenarios/checklists.md
new file mode 100644
index 0000000000..16712907ca
--- /dev/null
+++ b/articles/architecture-scenarios/checklists.md
@@ -0,0 +1,72 @@
+---
+title: Implementation Planning Checklists
+description: Links to checklists for your implementation.
+topics:
+ - SDLC
+ - checklists
+ - best practices
+ - implementation checklist
+contentType: reference
+useCase:
+ - implementation
+---
+# Implementation Planning Checklists
+
+Click the links below to download a checklist that corresponds to a phase in the SDLC (Software Development Lifecycle). You can open the checklist in any spreadsheet application and customize them to suit your needs.
+
+##  Analyze Checklist
+
+Analyze Checklist Download
+
+In the Analyze phase, analyze end-user business requirements and determine project goals as part of the high-level plan for the project. Convert the requirements and goals into system functions that the organization intends to develop. Activities include:
+
+* Gathering business requirements
+* Creating process diagrams
+* Performing detailed analysis
+* Alignment to project plan
+
+##  Design Checklist
+
+Design Checklist Download
+
+In the Design phase, describe the desired features and operations of the system, including business rules, pseudo-code, screen layouts, and other necessary documentation. Activities include:
+
+* Infrastructure design
+* System model design
+
+##  Build Checklist
+
+Build Checklist Download
+
+In the Build phase, develop the actual system through implementation of infrastructure and code. Activities include:
+
+* Infrastructure implementation
+* Code implementation
+
+##  Test Checklist
+
+Test Checklist Download
+
+In the Test phase, integrate and deploy all implemented code in the testing environment infrastructure. Testing then follows Software Testing Life Cycle activities to check the system for errors, bugs, and defects to verify that system features work as expected (or not). Activities include:
+
+* Write test cases
+* Execute test cases
+
+##  Deploy Checklist
+
+Deploy Checklist Download
+
+In the Deploy phase, deploy the system to either a staging or production environment, where actual users begin to operate and interact with it.
+
+Eventually, you deploy all components of the system to the production environment when you make a live release.
+
+##  Monitor Checklist
+
+Monitor Checklist Download
+
+In the Monitor phase, make enhancements, corrections, and changes to ensure the system continues to work and stays updated to meet the business objectives and support the needs of the users. Activities include:
+
+* Monitoring
+* Maintenance
+* Changes and adjustments
+* Upgrade and adapt to future needs
diff --git a/articles/architecture-scenarios/implementation-resources.md b/articles/architecture-scenarios/implementation-resources.md
new file mode 100644
index 0000000000..b4c4f6a955
--- /dev/null
+++ b/articles/architecture-scenarios/implementation-resources.md
@@ -0,0 +1,115 @@
+---
+title: Implementation Resources
+description: Learn about all the resources Auth0 provides to help you with your Auth0 implementation.
+toc: true
+topics:
+ - architecture
+ - api-auth
+ - sample-code
+ - sdks
+ - documentation
+ - guides
+ - quickstarts
+contentType: concept
+useCase:
+ - get-started
+ - implementation
+ - learning
+ - testing
+ - run-sample-code
+ - get-help
+ - enter-support-ticket
+---
+# Implementation Resources
+
+Auth0 provides a wealth of resources to help you effectively engage with our product and community. This list provides links to the resources available, by category.
+
+## Get started
+
+Resources designed to help you learn the basics of Auth0 include:
+
+* [**Getting Started documentation**](/getting-started): Explore the Auth0 Dashboard and common terms used for components of the Auth0 service. Gain a broad understanding of Auth0 and learn the terminology you might hear when working with Auth0 staff or reading our docs.
+
+* [**Get Started with Auth0 Video Series**](/videos/get-started): In these short videos, we cover how easy it is to complete the basic steps to use Auth0 with your applications. Watch the series before you start your project so you can get the benefit of our knowledge and experience with other customers. We cover tenant configuration, provisioning user stores and importing users, authentication, authorization, and branding and customization of everything shown to your users.
+
+* [**Architecture scenarios**](/architecture-scenarios): Review common architecture scenarios and learn how to implement them with Auth0. Scenarios include tutorials for common architecture patterns, such as a Single-Page Application (SPA) calling an API. High-level descriptions are useful for architects, while tutorials will help development teams.
+
+* [**Implementation guides**](/topics/guides): Learn how to implement commonly-used features, such as user management and multi-factor authentication (MFA). This information is useful for both architects and developers.
+
+## Learn
+
+Auth0 provides numerous tutorials, guides, white papers, and blog posts that focus on both learning and providing quick reference checks.
+
+* [**Docs site**](https://auth0.com/docs/): Browse through our docs to explore a wealth of available topics, or use our search to quickly find content related to a topic or term.
+
+* [**Feature descriptions and white papers**](https://auth0.com/learn/): Investigate short descriptions of features, industry case studies, and reference white papers. The Auth0 Learn site provides a quick overview of Auth0 features and their business value; it is helpful for project owners as well as architects and developers.
+
+* [**Blog posts**](https://auth0.com/blog/): Read blog posts written by experts on a variety of topics--from time-honored advice to breaking news in the identity space. Many blog posts are oriented toward architects and developers.
+
+## Run sample code
+
+Once your development team is ready to build, Auth0 provides sample programs, SDKs, and libraries to speed your project along.
+
+* [**Quickstarts**](/quickstarts): Investigate a rich array of small sample programs that demonstrate how to implement the key features you’ll want to include in your program, such as authentication, session management, profile updates, and logout. Quickstarts will give developers a head start on understanding how to integrate applications with Auth0.
+
+* [**Libraries and SDKs**](/libraries): Simplify your custom application development by using our extensive set of libraries and SDKs, which abstract many of the details of identity protocols for you. Auth0 SDKs support numerous languages and frameworks to simplify your integration with Auth0. We also provide a library for Lock, a login widget, that you can use across several platforms, including iOS and Android.
+
+* [**Management API**](/api/management/v2): Explore and manipulate objects, configurations, and settings within Auth0. The Management API Explorer allows you to quickly manipulate individual objects and settings on an *ad-hoc* basis and test API calls before coding them into your applications.
+
+* [**Authentication API**](/api/authentication): Authenticate and authorize users via the OIDC, OAuth, and SAML protocols. The Authentication API Explorer allows you to experiment with authentication and authorization flows, and test API calls before coding them into your applications.
+
+## Try out features and API calls
+
+While building, Auth0 allows you to experiment with and test out various product features.
+
+* **TRY buttons/links**: Quickly try out Auth0 product features. **TRY** buttons are located throughout Auth0 and allow you to experiment with connections, rules, hooks, and email templates.
+
+* [**Authentication API Explorer**](/api/authentication#introduction): Experiment with authentication and authorization flows, and test API calls before coding them into your applications.
+
+* [**Management API Explorer**](/api/management/v2): Quickly manipulate individual objects and settings on an *ad-hoc* basis and test API calls before coding them into your applications.
+
+* [**Postman Collections**](/api/postman): Easily dissect our APIs' calls using Postman by importing our Postman Collections.
+
+## Get help
+
+Auth0 resources that help you troubleshoot your implementation include:
+
+* [**Auth0 Community forum**](https://community.auth0.com/): Connect with the world of Auth0 via Auth0 posts, FAQs, and community Q&As. Architects and developers find this a valuable source of information for learning and connecting with others as well as getting help on issues.
+
+* [**Support Center**](https://support.auth0.com/): View and manage your subscription and tenants, file and view support requests, run automated production checks on a tenant, and view compliance information. Paid subscribers will find the support center a valuable resource if an issue or question cannot be solved by documentation or by searching the forum.
+
+ * [**Create support cases**](/support/tickets): Create and file a support case if you need help.
+
+ * [**Support Plans and Service Level Agreements**](/support#defect-responses): Learn about multiple levels of support available for purchase.
+
+ * [**Troubleshooting tips**](/onboarding/enterprise-support#what-to-check-before-logging-an-issue) and [**Information to include in your support case**](/onboarding/enterprise-support#information-to-provide-when-logging-an-issue): Get advice to help your development and support teams analyze issues.
+
+* [**Supported versions**](/support/matrix): Understand which versions of SDKs, browsers, and languages are supported. Architects and developers should review this to ensure your project employs languages, libraries, and SDKs that will allow your implementation to work with Auth0.
+
+* [**Feedback Portal**](https://auth0.com/feedback): Make product suggestions. (You can also do this via the Support Center if you want better visibility into what you’ve filed over time.) Architects and developers can use this site to provide feedback on the Auth0 product for consideration as enhancements in the future.
+
+* [**Professional Services**](/services): Engage our world-wide professional services team to help speed your project to success. Project owners will find this useful for learning how Auth0 identity experts can help accelerate your project or fill in any temporary skill gaps.
+
+## Setup and monitor operations
+
+When you're ready to plan your launch, Auth0 provides the following resources:
+
+* [**Pre-launch advice**](/pre-deployment) and [**Production check**](/pre-deployment/how-to-run-test): Get tips and tools to help you plan your launch. Project managers and development and operations teams should explore these tips to leverage advice for a smooth launch.
+
+* [**Operational policies**](/policies): Familiarize yourself with Auth0's policies, so you know lead times for operational requests. Policies are useful for an entire team, but project owners and operations teams in particular should be aware of Auth0's operational policies.
+
+* [**Status Dashboard**](https://status.auth0.com): Quickly determine the availability of Auth0 services and subscribe to status updates. Although service interruptions are rare, when one occurs Auth0 conducts a root cause analysis and publishes the results on this site. Operations and support teams should be familiar with how to check Auth0 status.
+
+* [**Monitor endpoints**](/monitoring): Learn how to integrate our monitoring endpoints into your monitoring infrastructure. This information is of particular use to operations teams and project owners.
+
+* [**Log data**](/logs): Learn about the types of logs Auth0 provides, log data retention, and tools you can use to export log data to external analytical tools for analysis and long-term data storage. This information is useful for developers and operations teams, as well as compliance teams interested in data retention.
+
+* [**Dashboard notices**](/architecture-scenarios/implementation/b2c/b2c-operations#notifications): Stay informed about important announcements from Auth0. From time to time, Auth0 notifies you of important information via your Auth0 Dashboard and (depending on the severity of the information) via email to your registered Auth0 Dashboard Admins. You should regularly log in to the Dashboard and check the bell icon at the top for any important notices.
+
+## Satisfy privacy, security, and compliance needs
+
+View info on Auth0’s privacy policy, security policy, compliance certifications, and how Auth0 can help you with your compliance needs. This information is useful for project owners as well as security, privacy teams, and procurement teams.
+
+* [Privacy and Cookie Policy](https://auth0.com/privacy)
+* [Security, Privacy and Compliance](https://auth0.com/security/)
+* [Compliance Frameworks and Certifications](/compliance)
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-architecture.md b/articles/architecture-scenarios/implementation/b2b/b2b-architecture.md
new file mode 100644
index 0000000000..b38753d752
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-architecture.md
@@ -0,0 +1,56 @@
+---
+title: Architecture
+description: How you configure your Auth0 tenant architecture affects your B2B IAM implementation.
+toc: true
+topics:
+ - b2b
+ - b2biam
+ - architecture
+contentType: concept
+useCase:
+ - tenant-architecture
+---
+# Architecture
+
+<%= include('../../_includes/_architecture/_introduction.md', { platform: 'b2b' }) %>
+
+## Tenant provision
+
+<%= include('../../_includes/_architecture/_tenant-provision.md', { platform: 'b2b' }) %>
+
+### Tenant provision for complex organizations
+
+In most cases, provisioning separate Auth0 tenants for your customer's organizations is not necessary. However, in certain circumstances this can be something that is valuable for reducing the complexity of your setup. For instance, we recommend provisioning a separate Auth0 tenant for your customers' organization as a best practice if:
+
+* Your customers' organizations have isolated users that aren't shared with other organizations.
+* You have some customer organizations that support more than one IdP. For example, your customer has their own IdP but also has some users that aren't in their IdP and whose credentials you will need to store. Or, your customer wants to provide for one or more social connections in addition to their enterprise IdP.
+
+If both of these situations are the case, then we recommend that you create separate Auth0 tenants for each customer that needs it. This allows you to have a separate custom domain for them and to easily customize their login experience, including [Home Realm Discovery](/architecture-scenarios/implementation/b2b/b2b-authentication#home-real-discovery) on their login page.
+
+::: warning
+Maintaining multiple Auth0 tenants can add complexity to your system and should not be done unless absolutely necessary.
+:::
+
+## Tenant association
+
+<%= include('../../_includes/_architecture/_tenant-association.md', { platform: 'b2b' }) %>
+
+## Custom domains
+
+<%= include('../../_includes/_architecture/_custom-domains.md', { platform: 'b2b' }) %>
+
+## SDLC support
+
+<%= include('../../_includes/_architecture/_sdlc-support.md', { platform: 'b2b' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'architecture' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-authentication.md b/articles/architecture-scenarios/implementation/b2b/b2b-authentication.md
new file mode 100644
index 0000000000..4414be9c8f
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-authentication.md
@@ -0,0 +1,127 @@
+---
+title: Authentication
+description: How authentication works in your B2B IAM implementation.
+toc: true
+topics:
+ - b2b
+ - b2biam
+ - authentication
+ - universal-login
+contentType: concept
+useCase:
+ - authentication
+---
+# Authentication
+
+<%= include('../../_includes/_authentication/_introduction.md', { platform: 'b2b' }) %>
+
+## Universal Login
+
+<%= include('../../_includes/_authentication/_universal-login.md', { platform: 'b2b' }) %>
+
+## Home realm discovery
+
+Home realm discovery (HRD) is the process of identifying which identity provider (or which connection in Auth0) the user belongs to *before* authenticating them. There are two ways HRD can occur:
+
+* Provide a way for the decision to be made at the application
+* Have Home Realm Discovery happen on the Universal Login page
+
+Your system may need to do either or both methods so it is important to understand all approaches to HRD so that you can apply the one(s) that make the most sense to your applications.
+
+::: panel Best practice
+If you don’t need to know ahead of time (for example, all of your users are in a shared user pool), then you don’t need to do HRD. You can allow users to authenticate first and then determine which organization they belong to using app metadata. HRD is really only needed if you have multiple connections within your Auth0 tenant.
+:::
+
+### Application driven HRD
+
+A common and effective way for determining which realm a user belongs to is when an application is branded for each organization. The organization has its own instance of the application. This copy or instance can be physically isolated (running on a separate set of servers) or virtually isolated (running on shared servers, but presented as if it could be isolated), and is generally denoted through either a custom hostname (`companyA.application1.yourcompany.com`) or path (`application1.yourcompany.com/companyA`).
+
+::: warning
+This method will only work if you are not sharing users between organizations. If you are sharing users within organizations, then you must support [Home Realm Discovery on the Universal Login Page](#hrd-through-universal-login)
+:::
+
+::: panel Best practice
+If your application already knows what connection (IdP) the user needs, then pass that along when you redirect the user to `/authorize` using the connection query parameter.
+:::
+
+If this is the case for your application(s) then home realm discovery is a simple matter of storing the Auth0 connection name with the organization specific application configuration and sending that connection name as a parameter when redirecting the user for Universal Login. Sending the connection parameter can be achieved by adding it as a query parameter when you redirect them to the authorize endpoint. For more information see the [Authentication API docs](/api/authentication#authorization-code-flow); however, you will generally accomplish this using the SDK for whichever language your application is written in.
+
+::: panel Best practice
+If an organization needs more than one IdP, then you will have to do a second round of Home Realm Discovery once identifying their organization. This can be achieved with Auth0 through creating a dedicated Auth0 tenant for that organization and creating an enterprise connection to that tenant.
+:::
+
+### HRD through Universal Login
+
+There are three main approaches to Home Realm Discovery through Universal Login:
+
+* Discover the realm through the user’s email subdomain.
+* Discover the realm by looking up a user identifier in some sort of map of identifier to realm map.
+* Allow the user to choose or enter their realm (or organization).
+
+In both of the first two approaches, you may consider doing “Identifier First Login”. This means that you present only the ability to enter an identifier first. After which you collect the user’s identifier, and then based on the identifier you either automatically redirect the user or present a way for the user to enter their password if redirection is unnecessary.
+
+::: warning
+Though it is possible to implement Identifier First Login or allow a user to select their organization at the application instead of on the Universal Login Page, this can add complexity with respect to single sign on as well as complexity associated with replicating that behavior in all of your applications. Instead Auth0 recommends implementing some form of HRD through Universal Login.
+:::
+
+#### HRD through Universal Login using the email subdomain
+
+The simplest way to implement home realm discovery on the universal login page is to utilize the email subdomain of the user’s identifier to map that to their Identity Provider. This, of course, only works in situations where the email subdomain will be a 1:1 mapping to an organization or at least to an Identity Provider. Auth0’s Lock widget can do this for you if you are using the domain map in an enterprise connection, however if you want to build this yourself, you can, but it requires you to build a mapping of email subdomain to connection.
+
+#### HRD through Universal Login using the Identifier to Realm Map
+
+A second, more complex alternative is to store a map of identifier’s to IdP and provide a public endpoint to access that information. Then on the Universal Login page you can find the connection and redirect back to /authorize with the connection. The main drawbacks to this approach are latency, and more importantly security when it comes to identifier discovery: if you’re using email addresses, this makes it much easier for someone to discover whether a particular email address is a user of yours.
+
+::: panel Best practice
+Any public endpoint should have rate limiting applied to it to prevent hackers from using it to discover information and to prevent denial of service attacks.
+:::
+
+#### HRD through Universal Login using user choice
+
+The other simple option is to allow your users to choose from a list, if you don’t mind making public the list of organizations who use your product, or by allowing the user to enter their organization name explicitly. Once the user tells you which organization they belong to, you can redirect back to Auth0 with the connection for that organization specified, or simply prompt them for their username and password if the connection is a database connection.
+
+## Username and password authentication
+
+<%= include('../../_includes/_authentication/_username-and-password-authentication.md', { platform: 'b2b' }) %>
+
+## Application integration
+
+<%= include('../../_includes/_authentication/_application-integration.md', { platform: 'b2b' }) %>
+
+## Anomaly detection
+
+<%= include('../../_includes/_authentication/_attack-protection.md', { platform: 'b2b' }) %>
+
+## SSO with legacy systems
+
+<%= include('../../_includes/_authentication/_sso-legacy.md', { platform: 'b2b' }) %>
+
+## Enterprise Login
+
+The “bring your own identity” scenario has become a must-have for almost all B2B applications. Most enterprise companies expect to be able to integrate their IdP into your application so their employees don't need to store another set of credentials. This is a valuable way of simplifying the user authentication experience without compromising security, and using [Universal Login](#universal-login) makes it easy to start adding support for [Enterprise Connections](/connections/identity-providers-enterprise) with minimal disruption.
+
+::: panel Best Practice
+Once you start supporting enterprise connections for users, you must do some form of [Home Realm Discovery](#home-realm-discovery) so that you can determine which connection to send the user to for authentication.
+:::
+
+With enterprise connection support, user identities and credentials are managed by the identity provider of your customers' organization, as well as certain identity claims - which Auth0 will use to populate the user [profile](/architecture-scenarios/implementation/b2b/b2b-profile-mgmt).
+
+::: panel Best Practice
+"Bring your own identity" is a great feature to provide, but if you don't support this from day one, and sometimes even if you do, you may have an organization that wants to switch to their own IdP after already having used the application for a while. You will need a way to [link user accounts](/users/concepts/overview-user-account-linking) to provide an effective way of associating the new identity with the old database identity.
+:::
+
+## Multi-factor authentication (MFA)
+
+<%= include('../../_includes/_authentication/_mfa.md', { platform: 'b2b' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'authentication' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-authorization.md b/articles/architecture-scenarios/implementation/b2b/b2b-authorization.md
new file mode 100644
index 0000000000..5d0ca8d405
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-authorization.md
@@ -0,0 +1,61 @@
+---
+title: Authorization
+description: User authorization and related planning considerations for your B2B IAM implementation.
+toc: true
+topics:
+ - b2b
+ - b2biam
+ - user-authorization
+contentType: concept
+useCase:
+ - user-authorization
+---
+# Authorization
+
+<%= include('../../_includes/_authorization/_introduction.md', { platform: 'b2b' }) %>
+
+## Application integration
+
+<%= include('../../_includes/_authorization/_application-integration.md', { platform: 'b2b' }) %>
+
+## API integration
+
+<%= include('../../_includes/_authorization/_api-integration.md', { platform: 'b2b' }) %>
+
+## Role Based Access Control (RBAC)
+
+<%= include('../../_includes/_authorization/_rbac.md', { platform: 'b2b' }) %>
+
+The core RBAC feature can be used in many multi-organization scenarios. See [Organization Data in an Access Tokens](#organization-data-in-an-access-token) for more information on how to ensure your setup can support your RBAC needs.
+
+## Machine-to-Machine (M2M) authorization
+
+<%= include('../../_includes/_authorization/_m2m.md', { platform: 'b2b' }) %>
+
+## Organization Data in an Access Token
+
+If you have a separate API from your application in your system that supports your multi-organization application, it is important to restrict operations to only the organization that the token was generated for. This requires that there is some sort of information in the access token to tell the API which organization the access token was issued for. This can be done in a couple of different ways depending on the answers to a couple of simple questions:
+
+1. Will the End Users in this organization potentially have more than one organization, or is each End User isolated to a specific organization?
+2. Will you be allowing any Machine-to-Machine (M2M) access to your API?
+3. If you are allowing Machine-to-Machine (M2M) access to your API, Will you have any developers who need a single client ID and secret to access multiple organizations (but not *all* organizations)?
+4. Will you be allowing the creating of third-party apps that require consent?
+
+If End Users are isolated to a single organization **and** you will either not be allowing M2M access to your API or you will have a separate client ID/secret for each organization that needs access **and** you will *not* be allowing third-party apps that require consent, then the simplest approach is to just create a custom claim in the access token [using rules for the user based tokens](#access-token-claims) and [using the client credentials hook for M2M calls](#machine-to-machine-m2m-authorization). You can store organization name in client metadata and extract it from rules or hooks to include in access_token as a custom claim. RBAC will work out of the box for this approach as well as long as each End User can only belong to one organization.
+
+If End Users have more than one organization they can belong to or you might give a single developer a client ID and secret for M2M calls to more than one organization, then you will be best served by creating a separate audience (a separate API instance in your Auth0 tenant) for each organization. This gives you a few nice abilities:
+1. First, it allows you to pass the audience as a first-class parameter to Auth0 without having to create a custom parameter. The benefit of this is that Auth0 will help enforce the existence of the audience, and it will pass it to your rules. It will also ensure that an issued refresh token will only work for the specific audience it was originally issued to.
+2. It allows you to restrict client grants to only specific organizations out of the box. The alternative is to create a more complicated client credentials hook to attempt to retrieve the restrictions from somewhere else and also require a much more complex and potentially troublesome way to tell the client credentials call which organization to issue the access token for.
+3. This also allows you to use the core RBAC feature with Auth0 and ensure that the End Users who have access to more than one organization can have a potentially different role for each organization.
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'authorization' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-branding.md b/articles/architecture-scenarios/implementation/b2b/b2b-branding.md
new file mode 100644
index 0000000000..b2da74226e
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-branding.md
@@ -0,0 +1,65 @@
+---
+title: Branding
+description: How to configure Auth0 items to reflect your brand and desired user experience.
+toc: true
+topics:
+ - b2b
+ - b2biam
+ - branding
+ - universal-login
+ - login-pages
+ - password-reset-pages
+ - custom-domains
+ - error-pages
+contentType: concept
+useCase:
+ - user-logout
+---
+# Branding
+
+<%= include('../../_includes/_branding/_introduction.md', { platform: 'b2b' }) %>
+
+## Universal login and login pages
+
+<%= include('../../_includes/_branding/_universal-login.md', { platform: 'b2b' }) %>
+
+## Branding login by organization
+
+Whether or not you need to do special customization on the Universal Login page is determined by how you plan to manage your customers’ organization. Before reading through this section, make sure you have read through the [Universal Login section](#universal-login-and-login-pages) and know how you are approaching organizations by reviewing [Multiple Organization Architecture](https://drive.google.com/a/auth0.com/file/d/1y2G8RNHTBujcCrnMRhp6_phQiRAkZzfF/view?usp=sharing).
+
+If your organization users will all be isolated from each other, than it’s important to make it clear on the Universal Login page which organization the login page is for. This can be done in a couple of ways:
+
+* Create JavaScript on the Universal Login Page that can pull resources from a CDN based on the organization presented to it.
+* Create a separate tenant for the organization and use the Universal Login page to customize as desired for that organization.
+
+## Custom domain naming
+
+<%= include('../../_includes/_branding/_custom-domain-naming.md', { platform: 'b2b' }) %>
+
+## Email template customization
+
+<%= include('../../_includes/_branding/_email-templates.md', { platform: 'b2b' }) %>
+
+## Password reset page customization
+
+<%= include('../../_includes/_branding/_password-reset.md', { platform: 'b2b' }) %>
+
+## Error page customization
+
+<%= include('../../_includes/_branding/_error-page.md', { platform: 'b2b' }) %>
+
+## Guardian multi-factor page customization
+
+<%= include('../../_includes/_branding/_guardian.md', { platform: 'b2b' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'branding' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-deployment.md b/articles/architecture-scenarios/implementation/b2b/b2b-deployment.md
new file mode 100644
index 0000000000..8f0c437182
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-deployment.md
@@ -0,0 +1,28 @@
+---
+title: Deployment Automation
+description: How Auth0 tooling helps to automate tenant deployment.
+topics:
+ - b2b
+ - b2biam
+ - tenants
+ - deployment
+contentType: concept
+useCase:
+ - tenant-deployment
+---
+
+# Deployment Automation
+
+<%= include('../../_includes/_deployment/_introduction.md', { platform: 'b2b' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'deployment' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-launch.md b/articles/architecture-scenarios/implementation/b2b/b2b-launch.md
new file mode 100644
index 0000000000..358e53464e
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-launch.md
@@ -0,0 +1,30 @@
+---
+classes: topic-page
+title: Launch Preparation
+description: Launch preparation considerations for your B2B IAM implementation.
+topics:
+ - b2b
+ - ciam
+ - launch
+contentType: concept
+useCase:
+ - launch
+---
+# Launch Preparation
+
+<%= include('../../_includes/_launch/_introduction.md', { platform: 'b2b' }) %>
+<%= include('../../../_includes/_topic-links', { links: [
+ 'architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-tenantcheck',
+ 'architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-testing',
+ 'architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-operations',
+ 'architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-compliance',
+ 'architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-support',
+ 'architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-launch'
+ ] }) %>
+
+## Project Planning Guide
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'launch' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-compliance.md b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-compliance.md
new file mode 100644
index 0000000000..01a2a4ce91
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-compliance.md
@@ -0,0 +1,24 @@
+---
+title: Compliance Readiness
+description: Compliance checks to perform before launch of your B2B IAM implementation.
+topics:
+ - b2b
+ - ciam
+ - launch
+ - compliance
+contentType: concept
+useCase:
+ - launch
+---
+
+# Compliance
+
+<%= include('../../../_includes/_launch/_compliance.md', { platform: 'b2b' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2b', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-launch.md b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-launch.md
new file mode 100644
index 0000000000..835be1391e
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-launch.md
@@ -0,0 +1,23 @@
+---
+title: Launch Day Preparation
+description: Launch preparation considerations for your B2B IAM implementation.
+topics:
+ - b2b
+ - ciam
+ - launch
+contentType: concept
+useCase:
+ - launch
+---
+
+# Launch Day Readiness
+
+<%= include('../../../_includes/_launch/_launch.md', { platform: 'b2b' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2b', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-operations.md b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-operations.md
new file mode 100644
index 0000000000..e4742e5f13
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-operations.md
@@ -0,0 +1,24 @@
+---
+title: Operations Readiness
+description: Operations checks to perform before launch of your B2B IAM implementation.
+topics:
+ - b2b
+ - ciam
+ - launch
+ - operations
+contentType: concept
+useCase:
+ - launch
+---
+
+# Operational Readiness
+
+<%= include('../../../_includes/_launch/_operations.md', { platform: 'b2b' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2b', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-support.md b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-support.md
new file mode 100644
index 0000000000..818c04db04
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-support.md
@@ -0,0 +1,23 @@
+---
+title: Support Readiness
+description: Support readiness for the launch of your B2B IAM implementation.
+topics:
+ - b2b
+ - ciam
+ - launch
+ - support
+contentType: concept
+useCase:
+ - launch
+---
+
+# Support Readiness
+
+<%= include('../../../_includes/_launch/_support.md', { platform: 'b2b' }) %>
+
+# Project Planning Guide
+<%= include('../../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2b', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-tenantcheck.md b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-tenantcheck.md
new file mode 100644
index 0000000000..bbe597465c
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-tenantcheck.md
@@ -0,0 +1,24 @@
+---
+title: Tenant Check
+description: Tenant Checks to perform before launch of your B2B IAM implementation.
+topics:
+ - b2b
+ - ciam
+ - launch
+ - configuration
+contentType: concept
+useCase:
+ - launch
+---
+
+# Tenant configuration check
+
+<%= include('../../../_includes/_launch/_tenant-check.md', { platform: 'b2b' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2b', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-testing.md b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-testing.md
new file mode 100644
index 0000000000..e3c2314ffe
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-launch/b2b-launch-testing.md
@@ -0,0 +1,24 @@
+---
+title: Testing Complete
+description: Testing preparation for the launch of your B2B IAM implementation.
+topics:
+ - b2b
+ - ciam
+ - launch
+ - testing
+contentType: concept
+useCase:
+ - launch
+---
+
+# Testing
+
+<%= include('../../../_includes/_launch/_testing.md', { platform: 'b2b' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2b', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-logout.md b/articles/architecture-scenarios/implementation/b2b/b2b-logout.md
new file mode 100644
index 0000000000..f818eb1ceb
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-logout.md
@@ -0,0 +1,58 @@
+---
+title: Logout
+description: User logout planning considerations for your B2B IAM implementation.
+topics:
+ - b2b
+ - b2biam
+ - logout
+ - sessions
+contentType: concept
+useCase:
+ - user-logout
+---
+# Logout
+
+<%= include('../../_includes/_logout/_introduction.md', { platform: 'b2b' }) %>
+
+## Single Logout
+
+If you are doing [Federated Logout](#federated-logout) you will likely also want to do Single Logout (SLO), and there are two main approaches you can take.
+
+::: warning
+SLO can add complexity to your system, so you need to ensure that you really need it before adding the extra development and maintenance time to your system.
+:::
+
+### Short-lived tokens
+
+::: panel Best Practice
+You want to avoid making too many calls to your Auth0 tenant to avoid rate limiting and poor performance. A best practice is to only request new tokens if tokens have expired and a user takes an action. This will avoid applications that are simply open, but not in use, from continually polling for new tokens.
+:::
+
+This is by far the simplest approach to Single Logout. Each application enforces a short time within which a user can use the system, say, 5-10 minutes. On each action a user performs, if the time has expired then either a redirect to Auth0 (for regular web apps), or [Silent Authentication](https://auth0.com/docs/api-auth/tutorials/silent-authentication) for client side Single Page Applications will be used to obtain new tokens. Ordinarily new tokens will be issued silently due to the Single Sign On (SSO) session. However, after logout, all applications will fail to get new tokens silently because the SSO session will have been removed, and the user will need to re-enter their credentials.
+
+::: warning
+If you are automatically forwarding the user directly to their own IdP as part of an enterprise connection using the connection parameter, this can break this technique unless you are also doing [Federated Logout](#federated-logout)
+:::
+
+### Build a logout service
+
+Another technique you can use is to build a logout service that can track and destroy application sessions. Each application would notify the logout service when it creates and removes a session. The (logout) service would either have direct access to all application's server side sessions and destroy them directly, or it will have the ability to make a back-channel call to each application to tell the application that it must remove its session.
+
+This technique can be quite effective as there is low-latency between when a user calls logout, and when they are then logged out of all applications. However it can add complexity and also additional development time for implementation. It will also require some way to ensure that new applications added to the system are added to this service.
+
+## Federated Logout
+
+[Federated User Logout](/logout/guides/logout-idps) may be something that you need to consider for your application. If you or your customers will be using a third-party IdP (i.e., something other than a [Database Identity Provider](/connections/database)) then the question of whether you need to log the user out of the IdP when they log out of your application is something you will need to answer. The answer depends on what your users would expect. If the application and/or IdP you use is tied closely to a customer organization and a central part of day-to-day operations, then it may be frustrating for users to get logged out of their IdP when they log out of your application. If not, then being logged out of the IdP may be expected, or in some cases even desired. In most B2B scenarios, our customers find that it is preferable *not* to perform federated logout for a user.
+
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'logout' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-operations.md b/articles/architecture-scenarios/implementation/b2b/b2b-operations.md
new file mode 100644
index 0000000000..7efd77e295
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-operations.md
@@ -0,0 +1,62 @@
+---
+title: Operations
+description: How to operationalize your Auth0 tenant environments.
+toc: true
+topics:
+ - b2b
+ - b2biam
+ - tenants
+ - operations
+contentType: concept
+useCase:
+ - tenant-operations
+---
+
+# Operations
+
+<%= include('../../_includes/_operations/_introduction.md', { platform: 'b2b' }) %>
+
+## Service status
+
+<%= include('../../_includes/_operations/_service-status.md', { platform: 'b2b' }) %>
+
+## Email provider setup
+
+<%= include('../../_includes/_operations/_email-provider.md', { platform: 'b2b' }) %>
+
+## Infrastructure
+
+<%= include('../../_includes/_operations/_infrastructure.md', { platform: 'b2b' }) %>
+
+## Logging
+
+<%= include('../../_includes/_operations/_logging.md', { platform: 'b2b' }) %>
+
+## Monitoring
+
+<%= include('../../_includes/_operations/_monitoring.md', { platform: 'b2b' }) %>
+
+## Notifications
+
+<%= include('../../_includes/_operations/_notifications.md', { platform: 'b2b' }) %>
+
+## Provisioning organizations
+
+<%= include('../../_includes/_provisioning/_organizations.md', { platform: 'b2b' }) %>
+
+## Self-Service IdP provisioning
+
+While Auth0 [connections](/identityproviders) make it easy to configure IdPs, it can be a time-consuming process to onboard customer organization IdPs especially if you are selling to new customer organizations on a regular basis or existing organizations have changing IdP requirements. As a result, many of our customers have found it worthwhile to build a self-service portal for their customers' organization admins so that they can configure their own IdPs. This cuts down on your IT department's workload. The [Auth0 Management API](/api/management/v2) provides all necessary [connection](/api/management/v2#!/Connections/get_connections) management functionality to achieve this.
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'operations' }) %>
+
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-profile-mgmt.md b/articles/architecture-scenarios/implementation/b2b/b2b-profile-mgmt.md
new file mode 100644
index 0000000000..bdc3ed3749
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-profile-mgmt.md
@@ -0,0 +1,57 @@
+---
+title: Profile Management
+description: User profile management planning considerations for your B2B IAM implementation.
+toc: true
+topics:
+ - b2b
+ - b2biam
+ - user-profiles
+contentType: concept
+useCase:
+ - profile-management
+ - manage-user-profiles
+---
+# Profile Management
+
+<%= include('../../_includes/_profile-mgmt/_introduction.md', { platform: 'b2b' }) %>
+
+## Metadata
+
+<%= include('../../_includes/_profile-mgmt/_metadata.md', { platform: 'b2b' }) %>
+
+## Password reset
+
+<%= include('../../_includes/_profile-mgmt/_password-reset.md', { platform: 'b2b' }) %>
+
+## Account verification
+
+<%= include('../../_includes/_profile-mgmt/_account-verification.md', { platform: 'b2b' }) %>
+
+## Blocking users
+
+<%= include('../../_includes/_profile-mgmt/_blocking-users.md', { platform: 'b2b' }) %>
+
+## Admin portal
+
+An admin portal is an application where you can create new users, edit a user’s profile, see activity about a user, etc. This application should be accessible by administrators only. Though Auth0 provides its management dashboard, it is not advised to give access to the management dashboard to many people as there are a lot of ways someone can unintentionally break your Auth0 tenant. Instead, Auth0 provides two other options:
+
+* [**Auth0 Management API**](/api/management/v2): With the Management API you can easily construct an application that provides administrators the ability to manage users. You can either incorporate this into an existing application that already exists for your administrators, or create a new one with a UI that matches your current applications.
+
+* [**Auth0 Delegated Administration Extension**](/extensions/delegated-admin/v3): This powerful and flexible extension allows you to customize a user administration experience. You can tailor this extension so that you can allow your customer admins to log in and allow them to only see and manage users within their organization.
+
+::: panel Best practice
+If you are providing your own way for an administrator to manage users, you should only allow administrators to send users a change password link through email rather than allowing administrators to set passwords directly. If you must go against this recommendation and allow your administrators to set someone’s password, you should force the user to change their password at their next login so that only they know the password (and not an administrator as well).
+:::
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'profile-mgmt' }) %>
+
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-provisioning.md b/articles/architecture-scenarios/implementation/b2b/b2b-provisioning.md
new file mode 100644
index 0000000000..8f2fe1e387
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-provisioning.md
@@ -0,0 +1,117 @@
+---
+title: Provisioning
+description: User provisioning functionality and considerations for your B2B IAM implementation.
+toc: true
+topics:
+ - b2b
+ - b2biam
+ - user-migration
+ - custom-db
+ - universal-login
+ - user-profiles
+contentType: concept
+useCase:
+ - user-provisioning
+ - store-user-data
+---
+# Provisioning
+
+<%= include('../../_includes/_provisioning/_introduction.md', { platform: 'b2b' }) %>
+
+## Provisioning organizations
+
+<%= include('../../_includes/_provisioning/_organizations.md', { platform: 'b2b' }) %>
+
+## User migration
+
+<%= include('../../_includes/_provisioning/_user-migration.md', { platform: 'b2b' }) %>
+
+## Provisioning organization users
+
+An organization should map directly to one of your business customers/partners. Each business/partner that you are working with has users who will be logging in. We call those end users *organization users*.
+There are two different approaches to how to store your organization users:
+
+* **Isolated to the organization**: Every user *belongs* to exactly one organization. It would not make sense for that user to be a part of more than one organization, and even if they were, it would make sense for them to have a separate “identity” for that other organization. For example, a retail employee that works part time at two different stores has two different logins for each of those stores even if the stores both use the SaaS application. To learn more, see [Provisioning users isolated to the organization](#provisioning-users-isolated-to-the-organization).
+* **Shared between organizations**: In a case like this, users either create credentials in your company, or they can access other organizations instances of your application using credentials from their own organization. A simple way to look at this is that one user may be authorized to access more than one organization’s instance of the application. A user would understand that they can use the same credentials to access both instances of an application. For example, some doctors contract with multiple clinics and may need to be able to sign into each separate clinic with their same credentials. To learn more, see [Provisioning users shared between organizations](#provisioning-users-shared-between-organizations).
+
+### Provisioning users isolated to the organization
+
+Isolating users to the organization can provide a nice clean barrier between organizations. If no users ever need to access more than one organization (or you would rather force them to create multiple accounts), then this is an attractive approach.
+
+You need to provision those users at the IdP level. Each of the organizations will have its own IdP for accomplishing this. This IdP will come in one of three flavors:
+
+* **Your Auth0 Tenant is the IdP**: A Database Connection in your main tenant dedicated to this organization.
+* **Organizations bring their own IdP**: You set up an Enterprise Connection for them.
+* **Organizations with more than one IdP**: This situation is a little more tricky becasue you have multiple options for approaching this situation. In descending order of complexity, these include:
+ * You convince them to create (or find that they already have) one main IdP that can route to their individual IdPs.
+ * You create separate organizations (e.g. customerorg-department1 and customerorg-department2) in your applications.
+ * You set up a new Auth0 tenant just for them and add as many IdPs as they need (which may include a database in Auth0) to that tenant, along with their own custom domain and branding.
+ * You make your existing tenant and login page more complex to handle [Home Realm Discovery](/architecture-scenarios/implementation/b2b/b2b-authentication#home-real-discovery) just for organizations that have more than one IdP.
+
+We recommend using Auth0 as an IdP as a starting point because it’s simple to implement a user invite workflow: an administrator creates a user; a randomly-generated password is created for that user, but never stored or shown to anyone; and then the user receives a welcome email with a link to set their password. Compared to other invite flows, the only thing special about this is that the person who is creating the user will have to either select the organization ahead of time, or the system will force the organization to match that of the user doing the inviting (in situations where there is an organization administrator who belongs to that organization only). To learn more, see [User invite](#user-invite).
+
+::: panel Best Practice
+If you can keep a main Auth0 tenant with a one-to-one mapping between organization and connection, it will greatly simplify your login system, making it more maintainable and extendable for the future. See [Multiple Organization Architecture documents: isolated users by organization](https://drive.google.com/a/auth0.com/file/d/1fzWWu7CUWaPpmaSO01gEhVYmkSXvV28l/view?usp=sharing) for a more in-depth view.
+:::
+
+### Provisioning users shared between organizations
+
+When sharing users between organizations, you will need a way to authorize access. Because you won’t know where a user might belong when authenticating, we typically recommend storing your users in a single domain and then figuring out which organizations they can access by using user app metadata. Because of this, provisioning will often be done by starting with a User Invite workflow for the single database connection, and then app metadata will be used to authorize access. User app metadata allows information to be stored in a user’s profile that can impact a user's capabilities but which a user cannot change. Let’s say I’m a doctor and I belong to Clinic A and Clinic B. I might have an organizations object in my app metadata that looks like: `{ “organizations”: [“clinicA”,”clinicB”] }`, and then when attempting to log into the app for Clinic B, a rule can check that Clinic B is in the `organizations` array.
+
+::: panel Best Practice
+Because users are shared, you won’t be able to determine who has access by isolating them to their own connection, therefore you will need to use their app metadata to make the determination. When provisioning, you will need a way to set the organizations they have access to or add a new organization to an already existing user.
+:::
+
+### Deprovisioning limitations
+
+<%= include('../../_includes/_provisioning/_deprovisioning.md', { platform: 'b2b' }) %>
+
+## User invite
+
+In most B2B scenarios, only particular individuals are allowed access to the application. As a result, it is often simpler to have an administrator provision user accounts rather than having users sign up and then have an administrator approve them. Provisioning can often be done in an automated fashion when users are added to a centralized system as well.
+
+There are three different personas who might be [inviting users](/design/creating-invite-only-applications):
+
+* An administrator at your company may create the users for each organization.
+* An administrator from each organization may be assigned to creating users.
+* Another system responsible for creating users mahy exist, and that system may then create a user in Auth0.
+Regardless of the audience, the technique can be similar, with the exception of the third option which would require the use of the management API and could not be done using the Delegated Administration Extension. The rest is a matter of using the right authorization model for the application.
+
+User invite can be accomplished in a few ways:
+
+* Using the [Delegated Administration Extension](/extensions/delegated-admin/v3)
+* Updating a pre-existing user administration system that you’ve already created to use the [Management API](/api/management/v2)
+* Creating a new application to do this using the Management API.
+
+::: panel Best Practice
+Whether you are using the Management API or the Delegated Administration Extension, it is important to create each user with a random temporary password and *not* store that password anywhere! Then, use the Management API to send an email to the user with a link to set their password. This ensures that the only person who knows the password is the user themselves.
+:::
+
+::: warning
+One of the main principles of OIDC is that no one except the user themselves ever knows their password. If you are doing an invite flow, have your backend system randomly generate a password and then discard it and have your user reset their password before ever logging in. Do not create a temporary password and give it to them to log in the first time.
+:::
+
+## Enterprise sign up
+
+Enterprise sign up is synonymous with sign in via [enterprise login](/architecture-scenarios/implementation/b2b/b2b-authentication#enterprise-login)—there’s no distinction here *per se*, as user [profile](/architecture-scenarios/implementation/b2b/b2b-profile-mgmt) creation happens automatically upon first enterprise login.
+
+::: panel best practice
+A nice advantage of allowing your customers to use their own IdP is that they can administer their users and assign roles and access in their own IdP setup instead of forcing you to build administration for them. Working out the mapping for those customers will make this much easier.
+:::
+
+::: warning
+ If mapping isn't enough and you must put some metadata in your system, keep in mind that Auth0 will not create the user until they log in to the system the first time. Therefore, you will need to use rule extensibility to pull the initial information from somewhere else, or force users to log in the first time before you can add the metadata.
+:::
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'provisioning' }) %>
+
diff --git a/articles/architecture-scenarios/implementation/b2b/b2b-qa.md b/articles/architecture-scenarios/implementation/b2b/b2b-qa.md
new file mode 100644
index 0000000000..2aa5556410
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2b/b2b-qa.md
@@ -0,0 +1,41 @@
+---
+title: Quality Assurance
+description: Quality Assurance considerations for your B2B IAM implementation.
+toc: true
+topics:
+ - qa
+ - b2b
+ - b2biam
+ - quality
+contentType: concept
+useCase:
+ - quality-assurance
+---
+# Quality Assurance
+
+<%= include('../../_includes/_qa/_introduction.md', { platform: 'b2b' }) %>
+
+## Unit testing
+
+<%= include('../../_includes/_qa/_unit-testing.md', { platform: 'b2b' }) %>
+
+## Integration testing
+
+<%= include('../../_includes/_qa/_integration-testing.md', { platform: 'b2b' }) %>
+
+## Mock testing
+
+<%= include('../../_includes/_qa/_mock-testing.md', { platform: 'b2b' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2b' }) %>
+
+## Multiple Organization Architecture (Multitenancy)
+
+<%= include('../../_includes/_multitenancy.md', { platform: 'b2b' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2b', self: 'qa' }) %>
+
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-architecture.md b/articles/architecture-scenarios/implementation/b2c/b2c-architecture.md
new file mode 100644
index 0000000000..9d01f715a0
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-architecture.md
@@ -0,0 +1,40 @@
+---
+title: Architecture
+description: How you configure your Auth0 tenant architecture affects your B2C IAM implementation.
+toc: true
+topics:
+ - b2c
+ - ciam
+ - tenants
+contentType: concept
+useCase:
+ - tenant-architecture
+---
+
+# Architecture
+
+<%= include('../../_includes/_architecture/_introduction.md', { platform: 'b2c' }) %>
+
+## Tenant provision
+
+<%= include('../../_includes/_architecture/_tenant-provision.md', { platform: 'b2c' }) %>
+
+## Tenant association
+
+<%= include('../../_includes/_architecture/_tenant-association.md', { platform: 'b2c' }) %>
+
+## Custom domains
+
+<%= include('../../_includes/_architecture/_custom-domains.md', { platform: 'b2c' }) %>
+
+## SDLC support
+
+<%= include('../../_includes/_architecture/_sdlc-support.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'architecture' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-authentication.md b/articles/architecture-scenarios/implementation/b2c/b2c-authentication.md
new file mode 100644
index 0000000000..daffa7e833
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-authentication.md
@@ -0,0 +1,52 @@
+---
+title: Authentication
+description: How authentication works in your B2C IAM implementation.
+toc: true
+topics:
+ - b2c
+ - ciam
+ - authentication
+ - universal-login
+contentType: concept
+useCase:
+ - authentication
+---
+# Authentication
+
+<%= include('../../_includes/_authentication/_introduction.md', { platform: 'b2c' }) %>
+
+## Universal Login
+
+<%= include('../../_includes/_authentication/_universal-login.md', { platform: 'b2c' }) %>
+
+## Username and password authentication
+
+<%= include('../../_includes/_authentication/_username-and-password-authentication.md', { platform: 'b2c' }) %>
+
+## Application integration
+
+<%= include('../../_includes/_authentication/_application-integration.md', { platform: 'b2c' }) %>
+
+## Anomaly detection
+
+<%= include('../../_includes/_authentication/_attack-protection.md', { platform: 'b2c' }) %>
+
+## SSO with legacy systems
+
+<%= include('../../_includes/_authentication/_sso-legacy.md', { platform: 'b2c' }) %>
+
+## Social authentication
+
+<%= include('../../_includes/_authentication/_social-authentication.md', { platform: 'b2c' }) %>
+
+## Multi-factor authentication (MFA)
+
+<%= include('../../_includes/_authentication/_mfa.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'authentication' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-authorization.md b/articles/architecture-scenarios/implementation/b2c/b2c-authorization.md
new file mode 100644
index 0000000000..4394f0b496
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-authorization.md
@@ -0,0 +1,39 @@
+---
+title: Authorization
+description: User authorization and related planning considerations for your B2C IAM implementation.
+toc: true
+topics:
+ - b2c
+ - ciam
+ - user-authorization
+contentType: concept
+useCase:
+ - user-authorization
+---
+# Authorization
+
+<%= include('../../_includes/_authorization/_introduction.md', { platform: 'b2c' }) %>
+
+## Application integration
+
+<%= include('../../_includes/_authorization/_application-integration.md', { platform: 'b2c' }) %>
+
+## API integration
+
+<%= include('../../_includes/_authorization/_api-integration.md', { platform: 'b2c' }) %>
+
+## Role Based Access Control (RBAC)
+
+<%= include('../../_includes/_authorization/_rbac.md', { platform: 'b2c' }) %>
+
+## Machine-to-Machine (M2M) Authorization
+
+<%= include('../../_includes/_authorization/_m2m.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'authorization' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-branding.md b/articles/architecture-scenarios/implementation/b2c/b2c-branding.md
new file mode 100644
index 0000000000..cba76c1648
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-branding.md
@@ -0,0 +1,52 @@
+---
+title: Branding
+description: How to configure Auth0 items to reflect your brand and desired user experience.
+toc: true
+topics:
+ - b2c
+ - ciam
+ - branding
+ - universal-login
+ - login-pages
+ - password-reset-pages
+ - custom-domains
+ - error-pages
+contentType: concept
+useCase:
+ - user-logout
+---
+# Branding
+
+<%= include('../../_includes/_branding/_introduction.md', { platform: 'b2c' }) %>
+
+## Universal login and login pages
+
+<%= include('../../_includes/_branding/_universal-login.md', { platform: 'b2c' }) %>
+
+## Custom domain naming
+
+<%= include('../../_includes/_branding/_custom-domain-naming.md', { platform: 'b2c' }) %>
+
+## Email template customization
+
+<%= include('../../_includes/_branding/_email-templates.md', { platform: 'b2c' }) %>
+
+## Password reset page customization
+
+<%= include('../../_includes/_branding/_password-reset.md', { platform: 'b2c' }) %>
+
+## Error page customization
+
+<%= include('../../_includes/_branding/_error-page.md', { platform: 'b2c' }) %>
+
+## Guardian multi-factor page customization
+
+<%= include('../../_includes/_branding/_guardian.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'branding' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-deployment.md b/articles/architecture-scenarios/implementation/b2c/b2c-deployment.md
new file mode 100644
index 0000000000..896280664b
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-deployment.md
@@ -0,0 +1,24 @@
+---
+title: Deployment Automation
+description: How Auth0 tooling helps to automate tenant deployment.
+topics:
+ - b2c
+ - ciam
+ - tenants
+ - deployment
+contentType: concept
+useCase:
+ - tenant-deployment
+---
+
+# Deployment Automation
+
+<%= include('../../_includes/_deployment/_introduction.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'deployment' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-launch.md b/articles/architecture-scenarios/implementation/b2c/b2c-launch.md
new file mode 100644
index 0000000000..8eed687f5e
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-launch.md
@@ -0,0 +1,30 @@
+---
+classes: topic-page
+title: Launch Preparation
+description: Launch preparation considerations for your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - launch
+contentType: concept
+useCase:
+ - launch
+---
+# Launch Preparation
+
+<%= include('../../_includes/_launch/_introduction.md', { platform: 'b2c' }) %>
+<%= include('../../../_includes/_topic-links', { links: [
+ 'architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-tenantcheck',
+ 'architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-testing',
+ 'architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-operations',
+ 'architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-compliance',
+ 'architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-support',
+ 'architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-launch'
+ ] }) %>
+
+## Project Planning Guide
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'launch' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-compliance.md b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-compliance.md
new file mode 100644
index 0000000000..1712d77cc6
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-compliance.md
@@ -0,0 +1,24 @@
+---
+title: Compliance Readiness
+description: Compliance checks to perform before launch of your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - launch
+ - compliance
+contentType: concept
+useCase:
+ - launch
+---
+
+# Compliance
+
+<%= include('../../../_includes/_launch/_compliance.md', { platform: 'b2c' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2c', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-launch.md b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-launch.md
new file mode 100644
index 0000000000..3459fb54f8
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-launch.md
@@ -0,0 +1,23 @@
+---
+title: Launch Day Preparation
+description: Launch preparation considerations for your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - launch
+contentType: concept
+useCase:
+ - launch
+---
+
+# Launch Day Readiness
+
+<%= include('../../../_includes/_launch/_launch.md', { platform: 'b2c' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2c', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-operations.md b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-operations.md
new file mode 100644
index 0000000000..eb2a8942e8
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-operations.md
@@ -0,0 +1,24 @@
+---
+title: Operations Readiness
+description: Operations checks to perform before launch of your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - launch
+ - operations
+contentType: concept
+useCase:
+ - launch
+---
+
+# Operational Readiness
+
+<%= include('../../../_includes/_launch/_operations.md', { platform: 'b2c' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2c', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-support.md b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-support.md
new file mode 100644
index 0000000000..188827213e
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-support.md
@@ -0,0 +1,23 @@
+---
+title: Support Readiness
+description: Support readiness for the launch of your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - launch
+ - support
+contentType: concept
+useCase:
+ - launch
+---
+
+# Support Readiness
+
+<%= include('../../../_includes/_launch/_support.md', { platform: 'b2c' }) %>
+
+# Project Planning Guide
+<%= include('../../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2c', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-tenantcheck.md b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-tenantcheck.md
new file mode 100644
index 0000000000..dc54e51cb3
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-tenantcheck.md
@@ -0,0 +1,24 @@
+---
+title: Tenant Check
+description: Tenant Checks to perform before launch of your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - launch
+ - configuration
+contentType: concept
+useCase:
+ - launch
+---
+
+# Tenant configuration check
+
+<%= include('../../../_includes/_launch/_tenant-check.md', { platform: 'b2c' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2c', self: '*ignore*' }) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-testing.md b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-testing.md
new file mode 100644
index 0000000000..6e313784cb
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-launch/b2c-launch-testing.md
@@ -0,0 +1,24 @@
+---
+title: Testing Complete
+description: Testing preparation for the launch of your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - launch
+ - testing
+contentType: concept
+useCase:
+ - launch
+---
+
+# Testing
+
+<%= include('../../../_includes/_launch/_testing.md', { platform: 'b2c' }) %>
+
+# Project Planning Guide
+
+<%= include('../../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+# Keep reading
+
+<%= include('../../../_includes/_keep-reading.md', { platform: 'b2c', self: '*ignore*' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-logout.md b/articles/architecture-scenarios/implementation/b2c/b2c-logout.md
new file mode 100644
index 0000000000..79659c64c7
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-logout.md
@@ -0,0 +1,23 @@
+---
+title: Logout
+description: User logout planning considerations for your B2C IAM implementation.
+topics:
+ - b2c
+ - ciam
+ - logout
+ - sessions
+contentType: concept
+useCase:
+ - user-logout
+---
+# Logout
+
+<%= include('../../_includes/_logout/_introduction.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'logout' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-operations.md b/articles/architecture-scenarios/implementation/b2c/b2c-operations.md
new file mode 100644
index 0000000000..b10ab32dcc
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-operations.md
@@ -0,0 +1,49 @@
+---
+title: Operations
+description: How to operationalize your Auth0 tenant environments.
+toc: true
+topics:
+ - b2c
+ - ciam
+ - tenants
+ - operations
+contentType: concept
+useCase:
+ - tenant-operations
+---
+
+# Operations
+
+<%= include('../../_includes/_operations/_introduction.md', { platform: 'b2c' }) %>
+
+## Service status
+
+<%= include('../../_includes/_operations/_service-status.md', { platform: 'b2c' }) %>
+
+## Email provider setup
+
+<%= include('../../_includes/_operations/_email-provider.md', { platform: 'b2c' }) %>
+
+## Infrastructure
+
+<%= include('../../_includes/_operations/_infrastructure.md', { platform: 'b2c' }) %>
+
+## Logging
+
+<%= include('../../_includes/_operations/_logging.md', { platform: 'b2c' }) %>
+
+## Monitoring
+
+<%= include('../../_includes/_operations/_monitoring.md', { platform: 'b2c' }) %>
+
+## Notifications
+
+<%= include('../../_includes/_operations/_notifications.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'operations' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-profile-mgmt.md b/articles/architecture-scenarios/implementation/b2c/b2c-profile-mgmt.md
new file mode 100644
index 0000000000..5065318caf
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-profile-mgmt.md
@@ -0,0 +1,48 @@
+---
+title: Profile Management
+description: User profile management planning considerations for your B2C IAM implementation.
+toc: true
+topics:
+ - b2c
+ - ciam
+ - user-profiles
+contentType: concept
+useCase:
+ - profile-management
+ - manage-user-profiles
+---
+# Profile Management
+
+<%= include('../../_includes/_profile-mgmt/_introduction.md', { platform: 'b2c' }) %>
+
+## Metadata
+
+<%= include('../../_includes/_profile-mgmt/_metadata.md', { platform: 'b2c' }) %>
+
+## Password reset
+
+<%= include('../../_includes/_profile-mgmt/_password-reset.md', { platform: 'b2c' }) %>
+
+## Account verification
+
+<%= include('../../_includes/_profile-mgmt/_account-verification.md', { platform: 'b2c' }) %>
+
+## Blocking users
+
+<%= include('../../_includes/_profile-mgmt/_blocking-users.md', { platform: 'b2c' }) %>
+
+## Linking user accounts
+
+<%= include('../../_includes/_profile-mgmt/_linking-accounts.md', { platform: 'b2c' }) %>
+
+## De-provisioning
+
+<%= include('../../_includes/_profile-mgmt/_de-provisioning.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'profile-mgmt' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-provisioning.md b/articles/architecture-scenarios/implementation/b2c/b2c-provisioning.md
new file mode 100644
index 0000000000..df2c065de1
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-provisioning.md
@@ -0,0 +1,39 @@
+---
+title: Provisioning
+description: User provisioning functionality and considerations for your B2C IAM implementation.
+toc: true
+topics:
+ - b2c
+ - ciam
+ - user-migration
+ - custom-db
+ - universal-login
+ - user-profiles
+contentType: concept
+useCase:
+ - user-provisioning
+ - store-user-data
+---
+# Provisioning
+
+<%= include('../../_includes/_provisioning/_introduction.md', { platform: 'b2c' }) %>
+
+## User migration
+
+<%= include('../../_includes/_provisioning/_user-migration.md', { platform: 'b2c' }) %>
+
+## Self sign up
+
+<%= include('../../_includes/_provisioning/_self-signup.md', { platform: 'b2c' }) %>
+
+## Social sign up
+
+<%= include('../../_includes/_provisioning/_social-signup.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'provisioning' }) %>
diff --git a/articles/architecture-scenarios/implementation/b2c/b2c-qa.md b/articles/architecture-scenarios/implementation/b2c/b2c-qa.md
new file mode 100644
index 0000000000..e27135e1cf
--- /dev/null
+++ b/articles/architecture-scenarios/implementation/b2c/b2c-qa.md
@@ -0,0 +1,36 @@
+---
+title: Quality Assurance
+description: Quality Assurance considerations for your B2C IAM implementation.
+toc: true
+topics:
+ - qa
+ - b2c
+ - ciam
+ - quality
+contentType: concept
+useCase:
+ - quality-assurance
+---
+# Quality Assurance
+
+<%= include('../../_includes/_qa/_introduction.md', { platform: 'b2c' }) %>
+
+## Unit testing
+
+<%= include('../../_includes/_qa/_unit-testing.md', { platform: 'b2c' }) %>
+
+## Integration testing
+
+<%= include('../../_includes/_qa/_integration-testing.md', { platform: 'b2c' }) %>
+
+## Mock testing
+
+<%= include('../../_includes/_qa/_mock-testing.md', { platform: 'b2c' }) %>
+
+## Project Planning Guide
+
+<%= include('../../_includes/_planning.md', { platform: 'b2c' }) %>
+
+## Keep reading
+
+<%= include('../../_includes/_keep-reading.md', { platform: 'b2c', self: 'qa' }) %>
diff --git a/articles/architecture-scenarios/implementations/mobile-api/api-implementation-nodejs.md b/articles/architecture-scenarios/implementations/mobile-api/api-implementation-nodejs.md
deleted file mode 100644
index f23828c963..0000000000
--- a/articles/architecture-scenarios/implementations/mobile-api/api-implementation-nodejs.md
+++ /dev/null
@@ -1,248 +0,0 @@
----
-description: The Node.js implementation of the API for the Mobile + API architecture scenario
-url: /architecture-scenarios/application/mobile-api/api-implementation-nodejs
-toc: true
----
-
-# Mobile + API: Node.js Implementation for the API
-
-This document is part of the [Mobile + API Architecture Scenario](/architecture-scenarios/application/mobile-api) and it explains how to implement the API in Node.js. Please refer to the scenario for information on the implemented solution.
-
-::: note
-The full source code for the Node.js API implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).
-:::
-
-## 1. Define the API endpoints
-
-We will use the [Express web application framework](http://expressjs.com/) to build our Node.js API.
-
-### Create a package.json File
-
-Create a folder for your API, navigate into it and run `npm init`. This will setup your `package.json` file.
-
-You can leave the default settings or change them as you see fit.
-
-Our sample's `package.json` looks like the following:
-
-```json
-{
- "name": "timesheets-api",
- "version": "1.0.0",
- "description": "API used to add timesheet entries for employees and contractors",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
- },
- "author": "Auth0",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
- },
- "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
-}
-```
-
-### Install the Dependencies
-
-Next, we need to set our dependencies. We will use the following modules:
-
-- **express**: This module adds the [Express web application framework](https://expressjs.com/).
-
-- **cors**: This module adds support for enabling [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) which is required since the API will be called from a Single Page Application running on a different domain inside a web browser.
-
-- **jwks-rsa**: This library retrieves RSA signing keys from a **JWKS** (JSON Web Key Set) endpoint. Using `expressJwtSecret` we can generate a secret provider that will provide the right signing key to `express-jwt` based on the `kid` in the JWT header. For more information refer to the [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
-
-- **express-jwt**: This module lets you authenticate HTTP requests using JWT tokens in your Node.js applications. It provides several functions that make working with JWTs easier. For more information refer to the [express-jwt GitHub repository](https://github.com/auth0/express-jwt).
-
-- **body-parser**: This is a Node.js body parsing middleware. It extracts the entire body portion of an incoming request stream and exposes it on `req.body` as something easier to interface with.For more information and several alternatives refer to the body-parser GitHub repository.
-
-To install these dependencies run the following:
-
-```bash
-npm install express cors express-jwt jwks-rsa body-parser express-jwt-authz --save
-```
-
-### Implement the Endpoints
-
-Navigate to your API directory and create a `server.js` file. Your code needs to:
-
-- Get the dependencies.
-- Implement the endpoint(s).
-- Launch the API server.
-
-This is our sample implementation:
-
-```js
-const express = require('express');
-const app = express();
-const jwt = require('express-jwt');
-const jwksRsa = require('jwks-rsa');
-const cors = require('cors');
-const bodyParser = require('body-parser');
-
-// Enable CORS
-app.use(cors());
-
-// Enable the use of request body parsing middleware
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({
- extended: true
-}));
-
-// Create timesheets API endpoint
-app.post('/timesheets', function(req, res){
- res.status(201).send({message: "This is the POST /timesheets endpoint"});
-})
-
-// Launch the API Server at localhost:8080
-app.listen(8080);
-```
-
-Launch your API server using `node server` and make an HTTP POST request to `localhost:8080/timesheets`. You should see a JSON response with the message `This is the POST /timesheets endpoint`.
-
-So now we have our endpoint but anyone can call it. Continue to the next paragraph to see how we can fix this.
-
-## 2. Secure the API endpoints
-
-In order to validate our token we will use the `jwt` function, provided by the [express-jwt middleware](https://github.com/auth0/express-jwt#usage), and the `jwks-rsa` to retrieve our secret. The libraries do the following:
-
-1. `express-jwt` will decode the token and pass the request, the header and the payload to `jwksRsa.expressJwtSecret`.
-
-1. `jwks-rsa` will then download all signing keys from the JWKS endpoint and see if a one of the signing keys matches the `kid` in the header of the JWT. If none of the signing keys match the incoming `kid`, an error will be thrown. If we have a match, we will pass the right signing key to `express-jwt`.
-
-1. `express-jwt` will the continue its own logic to validate the signature of the token, the expiration, `audience` and the `issuer`.
-
-The steps we will follow in our code are:
-
-- Create the middleware function to validate the Access Token.
-- Enable the use of the middleware in our routes.
-
-You can also write some code to actually save the timesheet to a database. This is our sample implementation (some code is omitted for brevity):
-
-```js
-// set dependencies - code omitted
-
-// Enable CORS - code omitted
-
-// Create middleware for checking the JWT
-const checkJwt = jwt({
- // Dynamically provide a signing key based on the kid in the header and the singing keys provided by the JWKS endpoint
- secret: jwksRsa.expressJwtSecret({
- cache: true,
- rateLimit: true,
- jwksRequestsPerMinute: 5,
- jwksUri: `https://${account.namespace}/.well-known/jwks.json`
- }),
-
- // Validate the audience and the issuer
- audience: '{YOUR_API_IDENTIFIER}', //replace with your API's audience, available at Dashboard > APIs
- issuer: 'https://${account.namespace}/',
- algorithms: [ 'RS256' ]
-});
-
-// Enable the use of request body parsing middleware - code omitted
-
-// create timesheets API endpoint - code omitted
-app.post('/timesheets', checkJwt, function(req, res){
- var timesheet = req.body;
-
- // Save the timesheet to the database...
-
- //send the response
- res.status(201).send(timesheet);
-});
-// launch the API Server at localhost:8080 - code omitted
-```
-
-If we launch our server now and do an HTTP POST to `localhost:8080/timesheets` we should get the error message `Missing or invalid token` (which is perfectly fine since we didn’t send an Access Token in our request).
-
-In order to test the working scenario as well we need to:
-
-- Get an Access Token. For details on how to do so refer to: [Get an Access Token](/architecture-scenarios/application/server-api#get-an-access-token).
-- Invoke the API while adding an `Authorization` header to our request with the value `Bearer ACCESS_TOKEN` (where *ACCESS_TOKEN* is the value of the token we retrieved in the first step).
-
-## 3. Check the application permissions
-
-In this step we will add to our implementation the ability to check if the application has permissions (or `scope`) to use our endpoint in order to create a timesheet. In particular we want to ensure that the token has the correct scope, which is `batch:upload`.
-
-In order to do this we will make use of the `express-jwt-authz` Node.js package, so go ahead and add that to your project:
-
-```bash
-npm install express-jwt-authz --save
-```
-
-Now it is as simple as adding a call to `jwtAuthz(...)` to your middleware to ensure that the JWT contain a particular scope in order to execute a particular endpoint.
-
-We will add an additional dependency. The **express-jwt-authz** library, which is used in conjunction with express-jwt, validates the [JWT](/jwt) and ensures it bears the correct permissions to call the desired endoint. For more information refer to the [express-jwt-authz GitHub repository](https://github.com/auth0/express-jwt-authz).
-
-This is our sample implementation (some code is omitted for brevity):
-
-```js
-// set dependencies - some code omitted
-const jwtAuthz = require('express-jwt-authz');
-
-// Enable CORS - code omitted
-
-// Create middleware for checking the JWT - code omitted
-
-// Enable the use of request body parsing middleware - code omitted
-
-// create timesheets API endpoint
-app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets']), function(req, res){
- var timesheet = req.body;
-
- // Save the timesheet to the database...
-
- //send the response
- res.status(201).send(timesheet);
-})
-
-// launch the API Server at localhost:8080 - code omitted
-```
-
-If we invoke our API with a token that does not include this scope we should get the error message Forbidden with the HTTP status code `403`. You can test this by removing this scope from your API.
-
-## 4. Determine the User Identity
-
-The `express-jwt` middleware which is used to validate the JWT, also sets the `req.user` with the information contained in the JWT. If you want to use the `sub` claim to identify the user uniquely, you can simply use `req.user.sub`.
-
-In the case of the timesheets application however, we want to use the email address of the user as the unique identifier.
-
-The first thing we need to do is to write a rule which will add the email address of the user to the `access_token`. Go to the [Rules section](${manage_url}/#/rules}) of the Dashboard and click on the __Create Rule__ button.
-
-You can give the rule a descriptive name, for example `Add email to Access Token`, and then use the following code for the rule:
-
-```js
-function (user, context, callback) {
- const namespace = 'https://api.exampleco.com/';
- context.accessToken[namespace + 'email'] = user.email;
- callback(null, user, context);
-}
-```
-
-The `namespace` is used to ensure the claim has a unique name and does not clash with the names of any of the standard OIDC claims. You can typically use the URL of your application or API as the namespace.
-
-::: note
-For more information on namespaced claims, refer to [User profile claims and scope](/api-auth/tutorials/adoption/scope-custom-claims).
-:::
-
-Next, inside your API, you can retrieve the value of the claim from `req.user`, and use that as the unique user identity which you can associate with timesheet entries.
-
-```js
-app.get('/timesheets', checkJwt, jwtAuthz(['read:timesheets']), function(req, res) {
- var timesheet = req.body;
-
- // Associate the timesheet entry with the current user
- var userId = req.user['https://api.exampleco.com/email'];
- timesheet.user_id = userId;
-
- // Save the timesheet to the database...
-
- //send the response
- res.status(201).send(timesheet);
-});
-```
\ No newline at end of file
diff --git a/articles/architecture-scenarios/implementations/mobile-api/mobile-implementation-android.md b/articles/architecture-scenarios/implementations/mobile-api/mobile-implementation-android.md
deleted file mode 100644
index 19ac56e82f..0000000000
--- a/articles/architecture-scenarios/implementations/mobile-api/mobile-implementation-android.md
+++ /dev/null
@@ -1,1406 +0,0 @@
----
-description: The Android implementation of the API for the Mobile + API architecture scenario
-url: /architecture-scenarios/application/mobile-api/mobile-implementation-android
-toc: true
----
-
-# Mobile + API: Android Implementation for the Mobile App
-
-This document is part of the [Mobile + API Architecture Scenario](/architecture-scenarios/application/mobile-api) and it explains how to implement the mobile application in Android. Please refer to the scenario for information on the implemented solution.
-
-## 1. Set Up the Application
-
-<%= include('../../../_includes/_package', {
- org: 'auth0-samples',
- repo: 'auth0-pnp-exampleco-timesheets',
- path: 'timesheets-mobile/android',
- requirements: [
- 'Android Studio 2.3',
- 'Android SDK 25',
- 'Emulator - Nexus 5X - Android 6.0'
- ]
-}) %>
-
-### Set the Dependencies
-
-For this implementation, we will use the following dependencies within the app’s `build.gradle` file:
-
-- [Auth0.Android](https://github.com/auth0/Auth0.Android): this package enables integration with Auth0 to authenticate users.
-- [OkHttp](http://square.github.io/okhttp/): this package provides an HTTP application to make requests to the Node.JS API.
-- [JWTDecode.Android](https://github.com/auth0/JWTDecode.Android): this package will assist with decoding JWTs.
-- AppCompat: this package lets us use the toolbar widget for navigation in our activities.
-
-```gradle
-dependencies {
- compile 'com.squareup.okhttp:okhttp:2.7.5'
- compile 'com.auth0.android:auth0:1.10.0'
- compile 'com.auth0.android:jwtdecode:1.1.1'
- compile 'com.android.support:appcompat-v7:25.3.1'
- testCompile 'junit:junit:4.12'
-}
-```
-
-### Update the Manifest
-
-Open the application's `AndroidManifest.xml` and add the internet permission:
-
-```xml
-
-```
-
-We’ll also update the application details to utilize the Toolbar widget:
-
-```xml
-
-
-```
-
-### Set Configuration Values
-
-Set your Auth0 Client ID, Auth0 Domain, and API’s url in the `strings.xml` resource located in `/res/values/strings.xml`:
-
-```xml
-
- ExampleCo Timesheets
- Log in
- ...
- ...
- http://10.0.2.2:8080/timesheets
-
-```
-
-### Create Package Structure
-
-For this implementation, create directories for activities, models, and utils in the application package.
-
-- `activities/`: this package will contain the `LoginActivity.java`, `TimeSheetActivity.java`, `FormActivity.java`, and `UserActivity.java`.
-- `models/`: this package will contain the `TimeSheet.java` and `User.java` data models.
-- `utils/`: this package will contain the `UserProfileManager.java`, `TimeSheetAdapter.java`, and `ImageTask.java`
-
-## 2. Authorize the User
-
-### Update the Manifest
-
-Open the app's `AndroidManifest.xml` and add the `LoginActivity`:
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-### Create the Login Activity Layout
-
-Next create `login_activity.xml`, the layout for the `LoginActivity`:
-
-```xml
-
-
-
-
-
-
-
-
-```
-
-### Create the Login Activity
-
-The `LoginActivity` will handle user authorization and be the initial screen users see. We'll create a `login()` method to initialize a `WebAuthProvider` and start authentication. Ensure you provide the correct scheme, audience, and scope to the `WebAuthProvider`. For this implementation we will use:
-
-- __scheme__: `demo`
-- __audience__: `https://api.exampleco.com/timesheets` (the Node.JS API)
-- __response_type__: `code`
-- __scope__: `create:timesheets read:timesheets openid profile email offline_access`. These scopes will enable us to `POST` and `GET` to the Node.JS API, as well as retrieve the user profile and a Refresh Token.
-
-```java
-private void login() {
- Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
- auth0.setOIDCConformant(true);
-
- WebAuthProvider.init(auth0)
- .withScheme("demo")
- .withAudience("https://api.exampleco.com/timesheets")
- .withResponseType(ResponseType.CODE)
- .withScope("create:timesheets read:timesheets openid profile email offline_access")
- .start(
- // ...
- );
-}
-```
-
-In the `login()` method, upon successful authentication we'll redirect the user to the `TimeSheetActivity`.
-
-```java
-package com.auth0.samples.activities;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.view.View;
-import android.widget.Button;
-import android.widget.Toast;
-
-import com.auth0.android.Auth0;
-import com.auth0.android.authentication.AuthenticationException;
-import com.auth0.android.jwt.JWT;
-import com.auth0.android.provider.AuthCallback;
-import com.auth0.android.provider.ResponseType;
-import com.auth0.android.provider.WebAuthProvider;
-import com.auth0.android.result.Credentials;
-import com.auth0.samples.R;
-import com.auth0.samples.models.User;
-import com.auth0.samples.utils.CredentialsManager;
-import com.auth0.samples.utils.UserProfileManager;
-
-public class LoginActivity extends Activity {
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.login_activity);
- Button loginWithTokenButton = (Button) findViewById(R.id.loginButton);
- loginWithTokenButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- login();
- }
- });
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- if (WebAuthProvider.resume(intent)) {
- return;
- }
- super.onNewIntent(intent);
- }
-
- private void login() {
- Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
- auth0.setOIDCConformant(true);
-
- WebAuthProvider.init(auth0)
- .withScheme("demo")
- .withAudience("https://api.exampleco.com/timesheets")
- .withResponseType(ResponseType.CODE)
- .withScope("create:timesheets read:timesheets openid profile email")
- .start(LoginActivity.this, new AuthCallback() {
- @Override
- public void onFailure(@NonNull final Dialog dialog) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- dialog.show();
- }
- });
- }
-
- @Override
- public void onFailure(final AuthenticationException exception) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(LoginActivity.this, "Error: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
- }
- });
- }
-
- @Override
- public void onSuccess(@NonNull final Credentials credentials) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
- }
- });
- startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
- }
- });
- }
-}
-```
-
-### Store the Credentials
-
-To store the credentials received after login, we’ll use the `CredentialsManager` from the Auth0.Android library and [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences.html) for storage.
-
-Before initializing the `WebAuthProvider` in the `login()` method, we can create the `CredentialsManager`. Passing an `AuthenticationAPIClient` to the `CredentialsManager` enables it to refresh the Access Tokens if they are expired.
-
-```java
-private void login() {
- Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
- auth0.setOIDCConformant(true);
-
- AuthenticationAPIClient authAPIClient = new AuthenticationAPIClient(auth0);
- SharedPreferencesStorage sharedPrefStorage = new SharedPreferencesStorage(this);
- final CredentialsManager credentialsManager = new CredentialsManager(authAPIClient, sharedPrefStorage);
-
- WebAuthProvider.init(auth0)
- // ...
- }
-```
-
-Now update the `login()` method so that credentials are stored via the `CredentialsManager` after a successful authentication.
-
-```java
-// ...
-@Override
-public void onSuccess(@NonNull final Credentials credentials) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
- }
- });
-
- credentialsManager.saveCredentials(credentials);
- startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
-// ...
-}
-```
-
-## 3. Get the User Profile
-
-### Create the User Model
-
-Create a simple User model that will be utilized by the `UserProfileManager` and `UserActivity`.
-
-```java
-package com.auth0.samples.models;
-
-public class User {
- private String email;
- private String name;
- private String pictureURL;
-
- public User(String email, String name, String pictureURL) {
- this.email = email;
- this.name = name;
- this.pictureURL = pictureURL;
- }
-
- public String getEmail() {
- return email;
- }
-
- public String getName() {
- return name;
- }
-
- public String getPictureURL() {
- return pictureURL;
- }
-}
-
-```
-
-### Store the User Profile
-
-To handle storing user profile information we'll create a manager class `UserProfileManager`. The `UserProfileManager` will use [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences.html) to store data.
-
-```java
-package com.auth0.samples.utils;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-import com.auth0.android.result.UserProfile;
-import com.auth0.samples.models.User;
-
-public class UserProfileManager {
-
- private static final String PREFERENCES_NAME = "auth0_user_profile";
- private static final String EMAIL = "email";
- private static final String NAME = "name";
- private static final String PICTURE_URL = "picture_url";
-
- public static void saveUserInfo(Context context, User userInfo) {
- SharedPreferences sp = context.getSharedPreferences(
- PREFERENCES_NAME, Context.MODE_PRIVATE);
-
- sp.edit()
- .putString(EMAIL, userInfo.getEmail())
- .putString(NAME, userInfo.getName())
- .putString(PICTURE_URL, userInfo.getPictureURL())
- .apply();
- }
-
- public static User getUserInfo(Context context) {
- SharedPreferences sp = context.getSharedPreferences(
- PREFERENCES_NAME, Context.MODE_PRIVATE);
-
- return new User(
- sp.getString(EMAIL, null),
- sp.getString(NAME, null),
- sp.getString(PICTURE_URL, null)
- );
- }
-
- public static void deleteUserInfo(Context context) {
- SharedPreferences sp = context.getSharedPreferences(
- PREFERENCES_NAME, Context.MODE_PRIVATE);
-
- sp.edit()
- .putString(EMAIL, null)
- .putString(NAME, null)
- .putString(PICTURE_URL, null)
- .apply();
- }
-}
-```
-
-Next, update the `login()` method in the `LoginActivity` to retrieve the ID Token and get the user profile from the token with the JWTDecode.Android library. Then store the user profile with the `UserProfileManager`.
-
-```java
-// ...
-@Override
-public void onSuccess(@NonNull final Credentials credentials) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
- }
- });
-
- credentialsManager.saveCredentials(credentials);
- JWT jwt = new JWT(credentials.getIdToken());
- User user = new User(
- jwt.getClaim("email").asString(),
- jwt.getClaim("name").asString(),
- jwt.getClaim("picture").asString()
- );
- UserProfileManager.saveUserInfo(LoginActivity.this, user);
-
- startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
-}
-// ...
-```
-
-## 4. Display UI Elements Conditionally Based on Scope
-
-To determine whether a user has permissions to perform certain actions, we can look at the `scope` that was granted to the user during the authentication process. The `scope` will contain a string with all the scopes granted to a user, so to determine whether a particular scope was granted, we simply need to look whether the string of scopes contain the substring for that particular scope.
-
-### Store the Scope
-
-First, we can update the `User` class to store the granted scopes, and then provide a helper method, `hasScope()` which can be used to determine whether the granted scopes contain a particular scope:
-
-```java
-public class User {
- private String email;
- private String name;
- private String pictureURL;
- private String grantedScope;
-
- public User(String email, String name, String pictureURL, String grantedScope) {
- this.email = email;
- this.name = name;
- this.pictureURL = pictureURL;
- this.grantedScope = grantedScope;
- }
-
- public String getEmail() {
- return email;
- }
-
- public String getGrantedScope() {
- return grantedScope;
- }
-
- public String getName() {
- return name;
- }
-
- public String getPictureURL() {
- return pictureURL;
- }
-
- public Boolean hasScope(String scope) {
- return grantedScope.contains(scope);
- }
-}
-```
-
-Also remember to update the `UserProfileManager` to store the extra field:
-
-```java
-public class UserProfileManager {
-
- private static final String PREFERENCES_NAME = "auth0_user_profile";
- private static final String EMAIL = "email";
- private static final String NAME = "name";
- private static final String PICTURE_URL = "picture_url";
- private static final String SCOPE = "scope";
-
- public static void saveUserInfo(Context context, User userInfo) {
- SharedPreferences sp = context.getSharedPreferences(
- PREFERENCES_NAME, Context.MODE_PRIVATE);
-
- sp.edit()
- .putString(EMAIL, userInfo.getEmail())
- .putString(NAME, userInfo.getName())
- .putString(PICTURE_URL, userInfo.getPictureURL())
- .putString(SCOPE, userInfo.getGrantedScope())
- .apply();
- }
-
- public static User getUserInfo(Context context) {
- SharedPreferences sp = context.getSharedPreferences(
- PREFERENCES_NAME, Context.MODE_PRIVATE);
-
- return new User(
- sp.getString(EMAIL, null),
- sp.getString(NAME, null),
- sp.getString(PICTURE_URL, null),
- sp.getString(SCOPE, null)
- );
- }
-
- public static void deleteUserInfo(Context context) {
- SharedPreferences sp = context.getSharedPreferences(
- PREFERENCES_NAME, Context.MODE_PRIVATE);
-
- sp.edit()
- .putString(EMAIL, null)
- .putString(NAME, null)
- .putString(PICTURE_URL, null)
- .putString(SCOPE, null)
- .apply();
- }
-}
-```
-
-Next, update the `LoginActivity` to pass along the `scope` so it can be stored in the `User` object:
-
-```java
-// ...
-@Override
-public void onSuccess(@NonNull final Credentials credentials) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
- }
- });
-
- credentialsManager.saveCredentials(credentials);
- JWT jwt = new JWT(credentials.getIdToken());
- String scopes = credentials.getScope();
- User user = new User(
- jwt.getClaim("email").asString(),
- jwt.getClaim("name").asString(),
- jwt.getClaim("picture").asString(),
- credentials.getScope()
- );
- UserProfileManager.saveUserInfo(LoginActivity.this, user);
-
- startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
-}
-// ...
-```
-
-### Display Approval Menu Based on Scope
-
-Now, we can display certain UI elements based on whether the user was granted a particular scope. As an example, we have an approval menu item which should only be visible to users who have been granted the `approve:timesheets` scope.
-
-Below you can see the code from the `BaseActivity` class which checks whether a user has the `approve:timesheets` scope, and based on that will set the visibility of the menu item which displays the approval activity:
-
-```java
-// ...
-@Override
-public boolean onCreateOptionsMenu(Menu menu) {
- Boolean canApprove = UserProfileManager.getUserInfo(this).hasScope("approve:timesheets");
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.actions, menu);
- MenuItem item = menu.findItem(R.id.action_approve);
- item.setVisible(canApprove);
- return super.onCreateOptionsMenu(menu);
-}
-// ...
-```
-
-## 5. Call the API
-
-### Update the Manifest
-
-Open the app's `AndroidManifest.xml` and add the `TimeSheetActivity`:
-
-```xml
-
-```
-
-### Create the Timesheets Activity Layouts
-
-Next create `timesheet_activity.xml`, the layout for the `TimeSheetsActivity`:
-
-```xml
-
-
-
-
-
-
-
-```
-
-The `ListView` widget will contain individual entries which are represented by the `item_entry.xml` layout:
-
-```xml
-
-
-
-
-
-
-
-
-
-```
-
-And for the Toolbar navigation on the `TimeSheetActivity`, we’ll create the `timesheet_action_menu.xml` menu resource (`/res/menu/`):
-
-```xml
-
-
-```
-
-### Create the Timesheet Model
-
-Create a model for working with timesheet data in our views:
-
-```java
-package com.auth0.samples.models;
-
-import java.util.Date;
-
-/**
- * Created by ej on 7/9/17.
- */
-
-public class TimeSheet {
- private String userID;
- private String projectName;
- private String date;
- private double hours;
- private int ID;
-
- public TimeSheet(String gUserID, String gProjectName, String gDate, double gHours, int gID) {
- this.userID = gUserID;
- this.projectName = gProjectName;
- this.date = gDate;
- this.hours = gHours;
- this.ID = gID;
- }
-
- public String getUserID() {
- return userID;
- }
-
- public String getProjectName() {
- return projectName;
- }
-
- public String getDateString() {
- return date;
- }
-
- public double getHours() {
- return hours;
- }
-
- public int getID() {
- return ID;
- }
-}
-```
-
-### Create the Timesheet Adapter
-
-The `TimeSheetAdapter` is a utility class which will take an array of timesheet entries and apply them to the `ListView` on the `TimeSheetActivity`.
-
-```java
-package com.auth0.samples.utils;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.TextView;
-import com.auth0.samples.R;
-import com.auth0.samples.models.TimeSheet;
-import java.util.ArrayList;
-
-public class TimeSheetAdapter extends ArrayAdapter {
-
- public TimeSheetAdapter(Context context, ArrayList timesheets) {
- super(context, 0, timesheets);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
-
- TimeSheet timesheet = getItem(position);
-
- if (convertView == null) {
- convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_entry, parent, false);
- }
-
- TextView tvUserID = (TextView) convertView.findViewById(R.id.tvUserID);
- TextView tvDate = (TextView) convertView.findViewById(R.id.tvDate);
- TextView tvProjectName = (TextView) convertView.findViewById(R.id.tvProjectName);
- TextView tvHours = (TextView) convertView.findViewById(R.id.tvHours);
-
- tvUserID.setText(timesheet.getUserID());
- tvDate.setText(timesheet.getDateString());
- tvProjectName.setText(timesheet.getProjectName());
- tvHours.setText(Double.toString(timesheet.getHours()));
-
- return convertView;
- }
-}
-```
-
-### Create the Timesheet Activity
-
-The `TimeSheetActivity` displays the timesheet entries for the logged in user which are stored on the server.
-
-- The `@string/api_url` is set to `http://10.0.2.2:8080/timesheets` so the Android Emulator can connect to the Node.JS API running on `http://localhost:8080`.
-- The `callAPI()` method retrieves timesheets from the Node.JS API.
-- The `processResults()` method takes the JSON response from `callAPI()` and converts it `TimeSheet` objects.
-- The `onCreateOptionsMenu()` and `onOptionsItemSelected()` methods handle the Toolbar widget navigation functionality.
-
-```java
-package com.auth0.samples.activities;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.ListView;
-import android.widget.Toast;
-
-import com.auth0.android.Auth0;
-import com.auth0.android.authentication.AuthenticationAPIClient;
-import com.auth0.android.authentication.storage.CredentialsManager;
-import com.auth0.android.authentication.storage.CredentialsManagerException;
-import com.auth0.android.authentication.storage.SharedPreferencesStorage;
-import com.auth0.android.callback.BaseCallback;
-import com.auth0.android.result.Credentials;
-import com.auth0.samples.R;
-import com.auth0.samples.utils.TimeSheetAdapter;
-import com.auth0.samples.models.TimeSheet;
-import com.squareup.okhttp.Callback;
-import com.squareup.okhttp.OkHttpClient;
-import com.squareup.okhttp.Request;
-import com.squareup.okhttp.Response;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-public class TimeSheetActivity extends AppCompatActivity {
-
- private ArrayList timesheets = new ArrayList<>();
-
- private String accessToken;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.timesheet_activity);
- Toolbar navToolbar = (Toolbar) findViewById(R.id.navToolbar);
- setSupportActionBar(navToolbar);
-
- Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
- auth0.setOIDCConformant(true);
-
- AuthenticationAPIClient authAPIClient = new AuthenticationAPIClient(auth0);
- SharedPreferencesStorage sharedPrefStorage = new SharedPreferencesStorage(this);
-
- CredentialsManager credentialsManager = new CredentialsManager(authAPIClient, sharedPrefStorage);
- credentialsManager.getCredentials(new BaseCallback() {
- @Override
- public void onSuccess(Credentials payload) {
- accessToken = payload.getAccessToken();
- callAPI();
- }
-
- @Override
- public void onFailure(CredentialsManagerException error) {
- Toast.makeText(TimeSheetActivity.this, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
- }
- });
- }
-
- private void callAPI() {
- final Request.Builder reqBuilder = new Request.Builder()
- .get()
- .url(getString(R.string.api_url))
- .addHeader("Authorization", "Bearer " + accessToken);
-
- OkHttpClient client = new OkHttpClient();
- Request request = reqBuilder.build();
- client.newCall(request).enqueue(new Callback() {
- @Override
- public void onFailure(Request request, IOException e) {
- Log.e("API", "Error: ", e);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(TimeSheetActivity.this, "An error occurred", Toast.LENGTH_SHORT).show();
- }
- });
- }
-
- @Override
- public void onResponse(final Response response) throws IOException {
- timesheets = processResults(response);
- final TimeSheetAdapter adapter = new TimeSheetAdapter(TimeSheetActivity.this, timesheets);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (response.isSuccessful()) {
- ListView listView = (ListView) findViewById(R.id.timesheetList);
- listView.setAdapter(adapter);
- adapter.addAll(timesheets);
- } else {
- Toast.makeText(TimeSheetActivity.this, "API call failed.", Toast.LENGTH_SHORT).show();
- }
- }
- });
- }
- });
- }
-
- private ArrayList processResults (Response response) {
- ArrayList timesheets = new ArrayList<>();
- try {
- String jsonData = response.body().string();
- if (response.isSuccessful()) {
- JSONArray timesheetJSONArray = new JSONArray(jsonData);
- for (int i = 0; i < timesheetJSONArray.length(); i++) {
- JSONObject timesheetJSON = timesheetJSONArray.getJSONObject(i);
- String userID = timesheetJSON.getString("user_id");
- String projectName = timesheetJSON.getString("project");
- String dateStr = timesheetJSON.getString("date");
- Double hours = timesheetJSON.getDouble("hours");
- int id = timesheetJSON.getInt("id");
-
- TimeSheet timesheet = new TimeSheet(userID, projectName, dateStr, hours, id);
- timesheets.add(timesheet);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return timesheets;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.timesheet_action_menu, menu);
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_new:
- startActivity(new Intent(TimeSheetActivity.this, FormActivity.class));
- break;
- case R.id.action_profile:
- startActivity(new Intent(TimeSheetActivity.this, UserActivity.class));
- break;
- default:
- return super.onOptionsItemSelected(item);
- }
- return true;
- }
-}
-```
-
-## 6. View the User Profile
-
-To display the logged in user’s profile we’ll create the `UserActivity`, a corresponding `user_activity.xml` layout, and the `user_action_menu.xml` for the Toolbar navigation. The view will display the user’s name, email, and profile picture.
-
-### Update the Manifest
-
-Open the app's `AndroidManifest.xml` and add the `UserActivity`:
-
-```xml
-
-```
-
-#### Create the User Activity Layouts
-
-Next create `user_activity.xml`, the layout for the `UserActivity`, with an `ImageView` for the profile picture and `TextViews` for the user's name and email.
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-```
-
-And create the `user_actions_menu.xml` for the `UserActivity` Toolbar:
-
-```xml
-
-
-```
-
-### Load the Profile Picture from URL
-
-In order to load the user profile picture from the URL, create a task which extends `AsyncTask` and executes in the background.
-
-```java
-package com.auth0.samples.utils;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.os.AsyncTask;
-import android.util.Log;
-import android.widget.ImageView;
-
-import java.io.InputStream;
-import java.net.URL;
-
-public class ImageTask extends AsyncTask {
-
- private ImageView bmImage;
-
- public ImageTask(ImageView bmImage) {
- this.bmImage = bmImage;
- }
-
- protected Bitmap doInBackground(String... urls) {
- String urldisplay = urls[0];
- Bitmap mIcon11 = null;
-
- try {
- InputStream in = new URL(urldisplay).openStream();
- mIcon11 = BitmapFactory.decodeStream(in);
- } catch (Exception e) {
- Log.e("Error", e.getMessage());
- e.printStackTrace();
- }
- return mIcon11;
- }
-
- protected void onPostExecute(Bitmap result) {
- bmImage.setImageBitmap(result);
- }
-}
-```
-
-### Create the User Activity
-
-In the `onCreate()` method we'll retrieve the user information from the `UserProfileManager` and set the values in the view. As before, the `onCreateOptionsMenu()` and `onOptionsItemSelected()` methods handle the Toolbar widget navigation functionality.
-
-```java
-package com.auth0.samples.activities;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.auth0.samples.R;
-import com.auth0.samples.utils.ImageTask;
-import com.auth0.samples.utils.UserProfileManager;
-
-public class UserActivity extends AppCompatActivity {
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.user_activity);
- Toolbar navToolbar = (Toolbar) findViewById(R.id.navToolbar);
- setSupportActionBar(navToolbar);
-
- TextView tvName = (TextView) findViewById(R.id.tvName);
- TextView tvEmail = (TextView) findViewById(R.id.tvEmail);
-
- tvName.setText(UserProfileManager.getUserInfo(this).getName());
- tvEmail.setText(UserProfileManager.getUserInfo(this).getEmail());
-
- new ImageTask((ImageView) findViewById(R.id.ivPicture))
- .execute(UserProfileManager.getUserInfo(this).getPictureURL());
-
- UserProfileManager.getUserInfo(this).getName();
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu items for use in the action bar
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.user_action_menu, menu);
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_new:
- startActivity(new Intent(UserActivity.this, FormActivity.class));
- break;
- case R.id.action_view:
- startActivity(new Intent(UserActivity.this, TimeSheetActivity.class));
- break;
- default:
- // If we got here, the user's action was not recognized.
- // Invoke the superclass to handle it.
- return super.onOptionsItemSelected(item);
-
- }
- return true;
- }
-}
-```
-
-## 7. Form for New Timesheets
-
-Next create the `FormActivity` and layout to handle creating new timesheet entries.
-
-### Update the Manifest
-
-Open the app's `AndroidManifest.xml` and add the `FormActivity`:
-
-```xml
-
-```
-
-### Create the Form Activity Layouts
-
-Create the `form_activity.xml` layout with `EditText` for the project name and hours worked inputs, and a `DatePicker` for the day worked.
-
-```xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-And create the `form_actions_menu.xml` for the `FormActivity` Toolbar:
-
-```xml
-
-
-```
-
-### Create the Form Activity
-
-- The `@string/api_url` is set to `http://10.0.2.2:8080/timesheets` so the Android Emulator can connect to the Node.JS API running on `http://localhost:8080`.
-- The `onCreate()` method initializes the form and collects the input for the `postAPI()` method when the submit button is pressed.
-- The `postAPI()` method will send the user input retrieved from the form to the Node.JS API in JSON format.
-- The `clearForm()` method clears the input forms.
-- The `onCreateOptionsMenu()` and `onOptionsItemSelected()` methods handle the Toolbar widget navigation functionality.
-
-```java
-package com.auth0.samples.activities;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.DatePicker;
-import android.widget.EditText;
-import android.widget.Toast;
-
-import com.auth0.android.Auth0;
-import com.auth0.android.authentication.AuthenticationAPIClient;
-import com.auth0.android.authentication.storage.CredentialsManager;
-import com.auth0.android.authentication.storage.CredentialsManagerException;
-import com.auth0.android.authentication.storage.SharedPreferencesStorage;
-import com.auth0.android.callback.BaseCallback;
-import com.auth0.android.result.Credentials;
-import com.auth0.samples.R;
-import com.squareup.okhttp.Callback;
-import com.squareup.okhttp.MediaType;
-import com.squareup.okhttp.OkHttpClient;
-import com.squareup.okhttp.Request;
-import com.squareup.okhttp.RequestBody;
-import com.squareup.okhttp.Response;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.IOException;
-import java.util.Calendar;
-import java.util.Date;
-
-public class FormActivity extends AppCompatActivity {
-
- private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
-
- private String accessToken;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.form_activity);
- Toolbar navToolbar = (Toolbar) findViewById(R.id.navToolbar);
- setSupportActionBar(navToolbar);
-
- Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
- auth0.setOIDCConformant(true);
-
- AuthenticationAPIClient authAPIClient = new AuthenticationAPIClient(auth0);
- SharedPreferencesStorage sharedPrefStorage = new SharedPreferencesStorage(this);
-
- CredentialsManager credentialsManager = new CredentialsManager(authAPIClient, sharedPrefStorage);
- credentialsManager.getCredentials(new BaseCallback() {
- @Override
- public void onSuccess(Credentials payload) {
- accessToken = payload.getAccessToken();
- }
-
- @Override
- public void onFailure(CredentialsManagerException error) {
- Toast.makeText(FormActivity.this, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
- }
- });
-
- Button submitTimeSheetButton = (Button) findViewById(R.id.submitTimeSheetButton);
- final EditText editProjectName = (EditText) findViewById(R.id.editProjectName);
- final EditText editHours = (EditText) findViewById(R.id.editHours);
- final DatePicker datePicker = (DatePicker) findViewById(R.id.datePicker);
-
- submitTimeSheetButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- int day = datePicker.getDayOfMonth();
- int month = datePicker.getMonth();
- int year = datePicker.getYear();
-
- Calendar calendar = Calendar.getInstance();
- calendar.set(year, month, day);
-
- postAPI(
- editProjectName.getText().toString(),
- calendar.getTime(),
- editHours.getText().toString()
- );
- }
- });
- }
-
- private void postAPI(String projectName, Date date, String hours) {
-
- JSONObject postBody = new JSONObject();
- try {
- postBody.put("project", projectName);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- try {
- postBody.put("date", date);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- try {
- postBody.put("hours", hours);
- } catch (JSONException e) {
- e.printStackTrace();
- }
- String postStr = postBody.toString();
-
- final Request.Builder reqBuilder = new Request.Builder()
- .post(RequestBody.create(MEDIA_TYPE_JSON, postStr))
- .url(getString(R.string.api_url))
- .addHeader("Authorization", "Bearer " + accessToken);
-
- OkHttpClient client = new OkHttpClient();
- Request request = reqBuilder.build();
-
- client.newCall(request).enqueue(new Callback() {
- @Override
- public void onFailure(Request request, IOException e) {
- Log.e("API", "Error: ", e);
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(FormActivity.this, "An error occurred", Toast.LENGTH_SHORT).show();
- }
- });
- }
-
- @Override
- public void onResponse(final Response response) throws IOException {
- final String resBody = response.body().string();
-
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (response.isSuccessful()) {
- clearForm((ViewGroup) findViewById(R.id.mainForm));
- Intent intent = new Intent(FormActivity.this, TimeSheetActivity.class);
- FormActivity.this.startActivity(intent);
- } else {
- Toast.makeText(FormActivity.this, "Timesheet creation failed.", Toast.LENGTH_SHORT).show();
- }
- }
- });
- }
- });
- }
-
- private void clearForm(ViewGroup group) {
- for (int i = 0, count = group.getChildCount(); i < count; ++i) {
- View view = group.getChildAt(i);
- if (view instanceof EditText) {
- ((EditText)view).setText("");
- }
-
- if(view instanceof ViewGroup && (((ViewGroup)view).getChildCount() > 0))
- clearForm((ViewGroup)view);
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.form_action_menu, menu);
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_view:
- startActivity(new Intent(FormActivity.this, TimeSheetActivity.class));
- break;
- case R.id.action_profile:
- startActivity(new Intent(FormActivity.this, UserActivity.class));
- break;
- default:
- return super.onOptionsItemSelected(item);
-
- }
- return true;
- }
-}
-```
-
-## Test the App
-
-Before continuing, ensure you have [implemented the Node.JS API](/architecture-scenarios/application/mobile-api/api-implementation-nodejs).
-
-1. Start the API by navigating to the API's directory in your terminal and entering the `node server` command.
-2. Open the mobile app in Android Studio and press the __Run__ button.
-3. Select the Nexus 5X API 23 virtual device.
-4. Once the emulator has loaded the mobile app, you can login user then, create and view timesheet entries from the running Node.JS API.
-
-That's it! You are done!
diff --git a/articles/architecture-scenarios/implementations/server-api/api-implementation-nodejs.md b/articles/architecture-scenarios/implementations/server-api/api-implementation-nodejs.md
deleted file mode 100644
index 8e3e42e6e4..0000000000
--- a/articles/architecture-scenarios/implementations/server-api/api-implementation-nodejs.md
+++ /dev/null
@@ -1,198 +0,0 @@
----
-title: "Server Client + API: Node.js Implementation for the API"
-description: The Node.js implementation of the API for the Server Client + API architecture scenario
-url: /architecture-scenarios/application/server-api/api-implementation-nodejs
----
-# Server Client + API: Node.js Implementation for the API
-
-::: panel Server + API Architecture Scenario
-This document is part of the [Server + API Architecture Scenario](/architecture-scenarios/application/server-api) and it explains how to implement the API in Node.js. Please refer to the scenario for information on the implemented solution.
-:::
-
-Full source code for the Node.js API implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).
-
-## 1. Define the API endpoint
-
-We will use the [Express web application framework](http://expressjs.com/) to build our Node.js API.
-
-### Create a package.json File
-
-Create a folder for your API, navigate into it and run `npm init`. This will setup your `package.json` file.
-
-You can leave the default settings or change them as you see fit.
-
-Our sample’s `package.json` looks like the following:
-
-```json
-{
- "name": "timesheets-api",
- "version": "1.0.0",
- "description": "API used to add timesheet entries for employees and contractors",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
- },
- "author": "Auth0",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
- },
- "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
-}
-```
-
-### Install the Dependencies
-
-Next, we need to set our dependencies. We will use the following modules:
-
-- **express**: This module adds the [Express web application framework](https://expressjs.com/).
-
-- **jwks-rsa**: This library retrieves RSA signing keys from a [**JWKS** (JSON Web Key Set)](/jwks) endpoint. Using `expressJwtSecret` we can generate a secret provider that will provide the right signing key to `express-jwt` based on the `kid` in the JWT header. For more information refer to the [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
-
-- **express-jwt**: This module lets you authenticate HTTP requests using JWT tokens in your Node.js applications. It provides several functions that make working with JWTs easier. For more information refer to the [express-jwt GitHub repository](https://github.com/auth0/express-jwt).
-
-- **body-parser**: This is a Node.js body parsing middleware. It extracts the entire body portion of an incoming request stream and exposes it on `req.body` as something easier to interface with.For more information and several alternatives refer to the body-parser GitHub repository.
-
-To install these dependencies run the following:
-
-```bash
-npm install express express-jwt jwks-rsa body-parser --save
-```
-
-### Implement the Endpoint
-
-Navigate to your API directory and create a `server.js` file. Your code needs to:
-- Set the dependencies.
-- Enable the request body parsing middleware.
-- Implement the endpoint.
-- Launch the API server.
-
-This is our sample implementation:
-
-```js
-// set dependencies
-const express = require('express');
-const app = express();
-const jwt = require('express-jwt');
-const jwksRsa = require('jwks-rsa');
-const bodyParser = require('body-parser');
-
-// enable the use of request body parsing middleware
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({
- extended: true
-}));
-
-// create timesheets upload API endpoint
-app.post('/timesheets/upload', function(req, res){
- res.status(201).send({message: "This is the POST /timesheets/upload endpoint"});
-})
-
-// launch the API Server at localhost:8080
-app.listen(8080);
-```
-
-Launch your API server using `node server` and make an HTTP POST request to `localhost:8080/timesheets/upload`. You should see a JSON response with a message `This is the POST /timesheets/upload endpoint`.
-
-So now we have our endpoint but anyone can call it. Continue to the next paragraph to see how we can fix this.
-
-## 2. Secure the API endpoint
-
-In order to validate our token we will use the `jwt` function, provided by the [express-jwt middleware](https://github.com/auth0/express-jwt#usage), and the `jwks-rsa` package to retrieve the public key from Auth0. The libraries do the following:
-
-1. `express-jwt` will decode the token and pass the request, the header and the payload to `jwksRsa.expressJwtSecret`.
-
-1. `jwks-rsa` will then download all signing keys from the JWKS endpoint and see if a one of the signing keys matches the `kid` in the header of the JWT. If none of the signing keys match the incoming `kid`, an error will be thrown. If we have a match, we will pass the right signing key to `express-jwt`.
-
-1. `express-jwt` will the continue its own logic to validate the signature of the token, the expiration, `audience` and the `issuer`.
-
-The steps we will follow in our code are:
-- Create the middleware function to validate the Access Token.
-- Enable the use of the middleware in our routes.
-
-This is also a good time for you to implement the logic to save the timesheet entries to a local database, or whatever other storage mechanism you may prefer. This is our sample implementation (some code is omitted for brevity):
-
-```js
-// set dependencies - code omitted
-
-// enable the use of request body parsing middleware - code omitted
-
-// Create middleware for checking the JWT
-const checkJwt = jwt({
- // Dynamically provide a signing key based on the kid in the header and the singing keys provided by the JWKS endpoint.
- secret: jwksRsa.expressJwtSecret({
- cache: true,
- rateLimit: true,
- jwksRequestsPerMinute: 5,
- jwksUri: `https://${account.namespace}/.well-known/jwks.json`
- }),
-
- // Validate the audience and the issuer.
- audience: process.env.AUTH0_AUDIENCE,
- issuer: `https://${account.namespace}/`,
- algorithms: ['RS256']
-});
-
-// create timesheets API endpoint
-app.post('/timesheets/upload', checkJwt, function(req, res){
- var timesheet = req.body;
-
- // Save the timesheet entry to the database...
-
- //send the response
- res.status(201).send(timesheet);
-})
-
-// launch the API Server at localhost:8080 - code omitted
-```
-
-If we launch our server now and do an HTTP POST to `localhost:8080/timesheets/upload` we should get the error message `Missing or invalid token` (which is perfectly fine since we didn’t send an Access Token in our request).
-
-In order to test the working scenario as well we need to:
-- Get an Access Token. For details on how to do so refer to: [Get an Access Token](/architecture-scenarios/application/server-api#get-an-access-token).
-- Invoke the API while adding an `Authorization` header to our request with the value `Bearer ACCESS_TOKEN` (where *ACCESS_TOKEN* is the value of the token we retrieved in the first step).
-
-## 3. Check the Client permissions
-
-In this step we will add to our implementation the ability to check if the client has permissions (or `scope`) to use our endpoint in order to upload a timesheet. In particular we want to ensure that the token has the correct scope, which is `batch:upload`.
-
-In order to do this we will make use of the `express-jwt-authz` Node.js package, so go ahead and add that to your project:
-
-```bash
-npm install express-jwt-authz --save
-```
-
-Now it is as simple as adding a call to `jwtAuthz(...)` to your middleware to ensure that the JWT contain a particular scope in order to execute a particular endpoint. This is our sample implementation (some code is omitted for brevity):
-
-```js
-// set dependencies - some code omitted
-const jwtAuthz = require('express-jwt-authz');
-
-// Create middleware for checking the JWT
-
-// Enable the use of request body parsing middleware
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({
- extended: true
-}));
-
-// Batch upload endpoint
-app.post('/timesheets/upload', checkJwt, jwtAuthz(['batch:upload']), function(req, res){
- var timesheet = req.body;
-
- // Save the timesheet entry to the database...
-
- //send the response
- res.status(201).send(timesheet);
-});
-
-// launch the API Server at localhost:8080 - code omitted
-```
-
-If we invoke our API with a token that does not include this scope we should get the error message Forbidden with the HTTP status code `403`. You can test this by removing this scope from your API.
-
-That's it! You are done!
diff --git a/articles/architecture-scenarios/implementations/server-api/cron-implementation-python.md b/articles/architecture-scenarios/implementations/server-api/cron-implementation-python.md
deleted file mode 100644
index 6387bc4761..0000000000
--- a/articles/architecture-scenarios/implementations/server-api/cron-implementation-python.md
+++ /dev/null
@@ -1,99 +0,0 @@
----
-title: "Server Client + API: Python Implementation for the Cron Job"
-description: The Python implementation of the server cron job for the Server Client + API architecture scenario
-url: /architecture-scenarios/application/server-api/cron-implementation-python
----
-
-# Server Client + API: Python Implementation for the Cron Job
-
-::: panel Server + API Architecture Scenario
-This document is part of the [Server + API Architecture Scenario](/architecture-scenarios/application/server-api) and it explains how to implement the server process in Python. Please refer to the [Server + API Architecture Scenario](/architecture-scenarios/application/server-api) document for information on the implemented solution.
-:::
-
-Full source code for the Python implementation of the server process can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-cron/python).
-
-## Get an Access Token
-
-In order to make the HTTP request to the Auth0 `/oauth/token` API endpoint we will use the libraries `json`, `urllib` and `urllib2`.
-
-This is our sample implementation:
-
-```python
-def main():
- import json, urllib, urllib2, httplib
-
- # Configuration Values
- domain = "${account.namespace}" # Your Auth0 Domain
- api_identifier = "API_IDENTIFIER" # API Identifier of your API
- client_id = "${account.clientId}" # Client ID of your Non Interactive Client
- client_secret = "YOUR_CLIENT_SECRET" # Client Secret of your Non Interactive Client
- api_url = "http://localhost:8080/timesheets/upload"
- grant_type = "client_credentials" # OAuth 2.0 flow to use
-
- # Get an Access Token from Auth0
- base_url = "https://{domain}".format(domain=domain)
- data = urllib.urlencode({'client_id': client_id,
- 'client_secret': client_secret,
- 'audience': api_identifier,
- 'grant_type': grant_type})
- req = urllib2.Request(base_url + "/oauth/token", data, headers={"Accept": "application/json"})
- response = urllib2.urlopen(req)
- resp_body = response.read()
- oauth = json.loads(resp_body)
- access_token = oauth['access_token']
-
-# Standard boilerplate to call the main() function.
-if __name__ == '__main__':
- main()
-```
-
-To test this modify your code to print the `access_token` variable and run the process using `python cron.py`.
-
-## Invoke the API
-
-The steps we follow in our implementation are:
-- Build a JSON object containing timesheet data and assign it to a `timesheet` variable.
-- Add the API URL and the `timesheet` variable contents to the request body using `urllib2.Request`.
-- Add the `Authorization` header to the request.
-- Set the `Content-Type` header to `application/json`.
-- Invoke the API using `urllib2.urlopen` and add some error handling.
-Retrieve the response using `json.loads` and print it in the console.
-
-This is our sample implementation (some code is omitted for brevity):
-
-```python
-def main():
- # import libraries - code omitted
-
- # Configuration Values - code omitted
-
- # Get an Access Token from Auth0 - code omitted
-
- #Post new timesheet to API
- timesheet = {'user_id': '007',
- 'date': '2017-05-10T17:40:20.095Z',
- 'project': 'StoreZero',
- 'hours': 5}
- req = urllib2.Request(api_url, data = json.dumps(timesheet))
- req.add_header('Authorization', 'Bearer ' + access_token)
- req.add_header('Content-Type', 'application/json')
-
- try:
- response = urllib2.urlopen(req)
- res = json.loads(response.read())
- print 'Created timesheet ' + str(res['id']) + ' for employee ' + str(res['user_id'])
- except urllib2.HTTPError, e:
- print 'HTTPError = ' + str(e.code) + ' ' + str(e.reason)
- except urllib2.URLError, e:
- print 'URLError = ' + str(e.reason)
- except httplib.HTTPException, e:
- print 'HTTPException'
- except Exception, e:
- print 'Generic Exception' + str(e)
-
-# Standard boilerplate to call the main() function - code omitted
-```
-
-To test this make sure your API is running and run the process using `python cron.py`.
-
-That's it! You are done!
diff --git a/articles/architecture-scenarios/implementations/spa-api/api-implementation-nodejs.md b/articles/architecture-scenarios/implementations/spa-api/api-implementation-nodejs.md
deleted file mode 100644
index 47fd09937f..0000000000
--- a/articles/architecture-scenarios/implementations/spa-api/api-implementation-nodejs.md
+++ /dev/null
@@ -1,249 +0,0 @@
----
-title: "SPA + API: Node.js Implementation for the API"
-description: The Node.js implementation of the API for the SPA + API architecture scenario
-url: /architecture-scenarios/application/spa-api/api-implementation-nodejs
-toc: true
----
-# SPA + API: Node.js Implementation for the API
-
-This document is part of the [SPA + API Architecture Scenario](/architecture-scenarios/application/spa-api) and it explains how to implement the API in Node.js. Please refer to the scenario for information on the implemented solution.
-
-::: note
-The full source code for the Node.js API implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).
-:::
-
-## 1. Define the API endpoints
-
-We will use the [Express web application framework](http://expressjs.com/) to build our Node.js API.
-
-### Create a package.json File
-
-Create a folder for your API, navigate into it and run `npm init`. This will setup your `package.json` file.
-
-You can leave the default settings or change them as you see fit.
-
-Our sample's `package.json` looks like the following:
-
-```json
-{
- "name": "timesheets-api",
- "version": "1.0.0",
- "description": "API used to add timesheet entries for employees and contractors",
- "main": "index.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
- },
- "author": "Auth0",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
- },
- "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
-}
-```
-
-### Install the Dependencies
-
-Next, we need to set our dependencies. We will use the following modules:
-
-- **express**: This module adds the [Express web application framework](https://expressjs.com/).
-
-- **cors**: This module adds support for enabling [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) which is required since the API will be called from a Single Page Application running on a different domain inside a web browser.
-
-- **jwks-rsa**: This library retrieves RSA signing keys from a **JWKS** (JSON Web Key Set) endpoint. Using `expressJwtSecret` we can generate a secret provider that will provide the right signing key to `express-jwt` based on the `kid` in the JWT header. For more information refer to the [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
-
-- **express-jwt**: This module lets you authenticate HTTP requests using JWT tokens in your Node.js applications. It provides several functions that make working with JWTs easier. For more information refer to the [express-jwt GitHub repository](https://github.com/auth0/express-jwt).
-
-- **body-parser**: This is a Node.js body parsing middleware. It extracts the entire body portion of an incoming request stream and exposes it on `req.body` as something easier to interface with.For more information and several alternatives refer to the body-parser GitHub repository.
-
-To install these dependencies run the following:
-
-```bash
-npm install express cors express-jwt jwks-rsa body-parser express-jwt-authz --save
-```
-
-### Implement the Endpoints
-
-Navigate to your API directory and create a `server.js` file. Your code needs to:
-
-- Get the dependencies.
-- Implement the endpoint(s).
-- Launch the API server.
-
-This is our sample implementation:
-
-```js
-const express = require('express');
-const app = express();
-const jwt = require('express-jwt');
-const jwksRsa = require('jwks-rsa');
-const cors = require('cors');
-const bodyParser = require('body-parser');
-
-// Enable CORS
-app.use(cors());
-
-// Enable the use of request body parsing middleware
-app.use(bodyParser.json());
-app.use(bodyParser.urlencoded({
- extended: true
-}));
-
-// Create timesheets API endpoint
-app.post('/timesheets', function(req, res){
- res.status(201).send({message: "This is the POST /timesheets endpoint"});
-})
-
-// Launch the API Server at localhost:8080
-app.listen(8080);
-```
-
-Launch your API server using `node server` and make an HTTP POST request to `localhost:8080/timesheets`. You should see a JSON response with the message `This is the POST /timesheets endpoint`.
-
-So now we have our endpoint but anyone can call it. Continue to the next paragraph to see how we can fix this.
-
-## 2. Secure the API endpoints
-
-In order to validate our token we will use the `jwt` function, provided by the [express-jwt middleware](https://github.com/auth0/express-jwt#usage), and the `jwks-rsa` to retrieve our secret. The libraries do the following:
-
-1. `express-jwt` will decode the token and pass the request, the header and the payload to `jwksRsa.expressJwtSecret`.
-
-1. `jwks-rsa` will then download all signing keys from the JWKS endpoint and see if a one of the signing keys matches the `kid` in the header of the JWT. If none of the signing keys match the incoming `kid`, an error will be thrown. If we have a match, we will pass the right signing key to `express-jwt`.
-
-1. `express-jwt` will the continue its own logic to validate the signature of the token, the expiration, `audience` and the `issuer`.
-
-The steps we will follow in our code are:
-
-- Create the middleware function to validate the Access Token.
-- Enable the use of the middleware in our routes.
-
-You can also write some code to actually save the timesheet to a database. This is our sample implementation (some code is omitted for brevity):
-
-```js
-// set dependencies - code omitted
-
-// Enable CORS - code omitted
-
-// Create middleware for checking the JWT
-const checkJwt = jwt({
- // Dynamically provide a signing key based on the kid in the header and the singing keys provided by the JWKS endpoint
- secret: jwksRsa.expressJwtSecret({
- cache: true,
- rateLimit: true,
- jwksRequestsPerMinute: 5,
- jwksUri: `https://${account.namespace}/.well-known/jwks.json`
- }),
-
- // Validate the audience and the issuer
- audience: '{YOUR_API_IDENTIFIER}', //replace with your API's audience, available at Dashboard > APIs
- issuer: 'https://${account.namespace}/',
- algorithms: [ 'RS256' ]
-});
-
-// Enable the use of request body parsing middleware - code omitted
-
-// create timesheets API endpoint - code omitted
-app.post('/timesheets', checkJwt, function(req, res){
- var timesheet = req.body;
-
- // Save the timesheet to the database...
-
- //send the response
- res.status(201).send(timesheet);
-});
-// launch the API Server at localhost:8080 - code omitted
-```
-
-If we launch our server now and do an HTTP POST to `localhost:8080/timesheets` we should get the error message `Missing or invalid token` (which is perfectly fine since we didn’t send an Access Token in our request).
-
-In order to test the working scenario as well we need to:
-
-- Get an Access Token. For details on how to do so refer to: [Get an Access Token](/architecture-scenarios/application/server-api#get-an-access-token).
-- Invoke the API while adding an `Authorization` header to our request with the value `Bearer ACCESS_TOKEN` (where *ACCESS_TOKEN* is the value of the token we retrieved in the first step).
-
-## 3. Check the application permissions
-
-In this step we will add to our implementation the ability to check if the application has permissions (or `scope`) to use our endpoint in order to create a timesheet. In particular we want to ensure that the token has the correct scope, which is `batch:upload`.
-
-In order to do this we will make use of the `express-jwt-authz` Node.js package, so go ahead and add that to your project:
-
-```bash
-npm install express-jwt-authz --save
-```
-
-Now it is as simple as adding a call to `jwtAuthz(...)` to your middleware to ensure that the JWT contain a particular scope in order to execute a particular endpoint.
-
-The **express-jwt-authz** library, which is used in conjunction with express-jwt, validates the [JWT](/jwt) and ensures it bears the correct permissions to call the desired endoint. For more information refer to the [express-jwt-authz GitHub repository](https://github.com/auth0/express-jwt-authz).
-
-This is our sample implementation (some code is omitted for brevity):
-
-```js
-// set dependencies - existing code omitted
-const jwtAuthz = require('express-jwt-authz');
-
-// Enable CORS - code omitted
-
-// Create middleware for checking the JWT - code omitted
-
-// Enable the use of request body parsing middleware - code omitted
-
-// create timesheets API endpoint
-app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets']), function(req, res){
- var timesheet = req.body;
-
- // Save the timesheet to the database...
-
- //send the response
- res.status(201).send(timesheet);
-})
-
-// launch the API Server at localhost:8080 - code omitted
-```
-
-If we invoke our API with a token that does not include this scope we should get the error message Forbidden with the HTTP status code `403`. You can test this by removing this scope from your API.
-
-## 4. Determine the User Identity
-
-The `express-jwt` middleware which is used to validate the JWT, also sets the `req.user` with the information contained in the JWT. If you want to use the `sub` claim to identify the user uniquely, you can simply use `req.user.sub`.
-
-In the case of the timesheets application however, we want to use the email address of the user as the unique identifier.
-
-The first thing we need to do is to write a rule which will add the email address of the user to the `access_token`. Go to the [Rules section](${manage_url}/#/rules}) of the Dashboard and click on the __Create Rule__ button.
-
-You can give the rule a descriptive name, for example `Add email to Access Token`, and then use the following code for the rule:
-
-```js
-function (user, context, callback) {
- const namespace = 'https://api.exampleco.com/';
- context.accessToken[namespace + 'email'] = user.email;
- callback(null, user, context);
-}
-```
-
-The `namespace` is used to ensure the claim has a unique name and does not clash with the names of any of the standard OIDC claims. You can typically use the URL of your application or API as the namespace.
-
-::: note
-For more information on namespaced claims, refer to [User profile claims and scope](/api-auth/tutorials/adoption/scope-custom-claims).
-:::
-
-Next, inside your API, you can retrieve the value of the claim from `req.user`, and use that as the unique user identity which you can associate with timesheet entries.
-
-```js
-app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets']), function(req, res){
-
- var timesheet = req.body;
-
- // Associate the timesheet entry with the current user
- var userId = req.user['https://api.exampleco.com/email'];
- timesheet.user_id = userId;
-
- // Save the timesheet to the database...
-
- //send the response
- res.status(201).send(timesheet);
-});
-```
diff --git a/articles/architecture-scenarios/implementations/spa-api/spa-implementation-angular2.md b/articles/architecture-scenarios/implementations/spa-api/spa-implementation-angular2.md
deleted file mode 100644
index 05232fe734..0000000000
--- a/articles/architecture-scenarios/implementations/spa-api/spa-implementation-angular2.md
+++ /dev/null
@@ -1,500 +0,0 @@
----
-title: "SPA + API: Angular 2 Implementation for the SPA"
-description: The Angular 2 implementation of the SPA for the SPA + API architecture scenario
-url: /architecture-scenarios/application/spa-api/spa-implementation-angular2
-toc: true
----
-
-# SPA + API: Angular 2 Implementation for the SPA
-
-This document is part of the [SPA + API Architecture Scenario](/architecture-scenarios/application/spa-api) and it explains how to implement the SPA in Angular 2. Please refer to the scenario for information on the implemented solution.
-
-::: note
-The full source code for the Angular 2 implementation of the SPA can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-spa/angular).
-:::
-
-## 1. Configuration
-
-Your application will require certain configuration information. Before carrying on with the rest of the implementation, create an `AuthConfig` interface which will contain various configuration values. Place this interface in a file called `auth0-variables.ts`.
-
-```js
-interface AuthConfig {
- clientID: string;
- domain: string;
- callbackURL: string;
- apiUrl: string;
-}
-
-export const AUTH_CONFIG: AuthConfig = {
- clientID: '',
- domain: '',
- callbackURL: 'http://localhost:4200/callback',
- apiUrl: ''
-};
-```
-
-## 2. Authorize the User
-
-### Create an Authorization Service
-
-The best way to manage and coordinate the tasks necessary for user authentication is to create a reusable service. With the service in place, you'll be able to call its methods throughout your application. An instance of the `WebAuth` object from [auth0.js](/libraries/auth0js) can be created in the service.
-
-```js
-import { Injectable } from '@angular/core';
-import { AUTH_CONFIG } from './auth0-variables';
-import { Router } from '@angular/router';
-import 'rxjs/add/operator/filter';
-import auth0 from 'auth0-js';
-
-@Injectable()
-export class AuthService {
-
- userProfile: any;
- requestedScopes: string = 'openid profile read:timesheets create:timesheets';
-
- auth0 = new auth0.WebAuth({
- clientID: AUTH_CONFIG.clientID,
- domain: AUTH_CONFIG.domain,
- responseType: 'token id_token',
- audience: AUTH_CONFIG.apiUrl,
- redirectUri: AUTH_CONFIG.callbackURL,
- scope: this.requestedScopes
- });
-
- constructor(public router: Router) {}
-
- public login(): void {
- this.auth0.authorize();
- }
-
- public handleAuthentication(): void {
- this.auth0.parseHash((err, authResult) => {
- if (authResult && authResult.accessToken && authResult.idToken) {
- window.location.hash = '';
- this.setSession(authResult);
- this.router.navigate(['/home']);
- } else if (err) {
- this.router.navigate(['/home']);
- console.log(err);
- alert('Error: <%= "${err.error}" %>. Check the console for further details.');
- }
- });
- }
-
- private setSession(authResult): void {
- // Set the time that the Access Token will expire at
- const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
-
- // If there is a value on the scope param from the authResult,
- // use it to set scopes in the session for the user. Otherwise
- // use the scopes as requested. If no scopes were requested,
- // set it to nothing
- const scopes = authResult.scope || this.requestedScopes || '';
-
- localStorage.setItem('access_token', authResult.accessToken);
- localStorage.setItem('id_token', authResult.idToken);
- localStorage.setItem('expires_at', expiresAt);
- localStorage.setItem('scopes', JSON.stringify(scopes));
- }
-
- public logout(): void {
- // Remove tokens and expiry time from localStorage
- localStorage.removeItem('access_token');
- localStorage.removeItem('id_token');
- localStorage.removeItem('expires_at');
- localStorage.removeItem('scopes');
- // Go back to the home route
- this.router.navigate(['/']);
- }
-
- public isAuthenticated(): boolean {
- // Check whether the current time is past the
- // Access Token's expiry time
- const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
- return new Date().getTime() < expiresAt;
- }
-
- public userHasScopes(scopes: Array): boolean {
- const grantedScopes = JSON.parse(localStorage.getItem('scopes')).split(' ');
- return scopes.every(scope => grantedScopes.includes(scope));
- }
-}
-```
-
-The service includes several methods for handling authentication.
-
-- __login__: calls `authorize` from auth0.js which initiates [universal login](/hosted-pages/login)
-- __handleAuthentication__: looks for an authentication result in the URL hash and processes it with the `parseHash` method from auth0.js
-- __setSession__: sets the user's `access_token`, `id_token`, and a time at which the `access_token` will expire
-- __logout__: removes the user's tokens from browser storage
-- __isAuthenticated__: checks whether the expiry time for the `access_token` has passed
-
-### Process the Authentication Result
-
-When a user authenticates via universal login and is then redirected back to your application, their authentication information will be contained in a URL hash fragment. The `handleAuthentication` method in the `AuthService` is responsibile for processing the hash.
-
-Call `handleAuthentication` in your app's root component so that the authentication hash fragment can be processed when the app first loads after the user is redirected back to it.
-
-```js
-// src/app/app.component.ts
-
-import { Component } from '@angular/core';
-import { AuthService } from './auth/auth.service';
-
-@Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
-})
-
-export class AppComponent {
-
- constructor(public auth: AuthService) {
- auth.handleAuthentication();
- }
-}
-```
-
-### Add the Callback Component
-
-Using universal login means that users are taken away from your application to a page hosted by Auth0. After they successfully authenticate, they are returned to your application where a client-side session is set for them.
-
-You can choose to have users return to any URL in your application that you like; however, it is recommended that you create a dedicated callback route to serve as a central location that the user will be returned to upon successful authentication. Having a single callback route is beneficial for two main reasons:
-
-- It prevents the need to whitelist multiple (and sometimes unknown) callback URLs
-- It serves as a place to show a loading indicator while your application sets the user's client-side session
-
-Create a component named `CallbackComponent` and populate it with a loading indicator.
-
-```html
-
-
-
-
-
-```
-
-::: note
-This example assumes some kind of loading spinner is available in an `assets` directory. See the downloadable sample for a demonstration.
-:::
-
-After authentication, users will be taken to the `/callback` route for a brief time where they will be shown a loading indicator. During this time, their client-side session will be set, after which they will be redirected to the `/home` route.
-
-## 3. Get the User Profile
-
-::: panel Extract info from the token
-This section shows how to retrieve the user info using the `access_token` and the [/userinfo endpoint](/api/authentication#get-user-info). Alternatively, you can just decode the `id_token` [using a library](https://jwt.io/#libraries-io) (make sure you validate it first). The output will be the same. If you need additional user information consider using the [our Management API](/api/management/v2#!/Users/get_users_by_id).
-:::
-
-To obtain the user's profile, update the existing `AuthService` class. Add a `getProfile` function which will extract the user's `access_token` from local storage, and then pass that call the `userInfo` function to retrieve the user's information.
-
-```js
-// Existing code from the AuthService class is omitted in this code sample for brevity
-@Injectable()
-export class AuthService {
- public getProfile(cb): void {
- const accessToken = localStorage.getItem('access_token');
- if (!accessToken) {
- throw new Error('Access Token must exist to fetch profile');
- }
-
- const self = this;
- this.auth0.client.userInfo(accessToken, (err, profile) => {
- if (profile) {
- self.userProfile = profile;
- }
- cb(err, profile);
- });
- }
-}
-```
-
-You can now simply call this function from any service where you want to retrieve and display information about the user.
-
-For example you may choose to create a new component to display the user's profile information:
-
-```js
-import { Component, OnInit } from '@angular/core';
-import { AuthService } from './../auth/auth.service';
-
-@Component({
- selector: 'app-profile',
- templateUrl: './profile.component.html',
- styleUrls: ['./profile.component.css']
-})
-export class ProfileComponent implements OnInit {
-
- profile: any;
-
- constructor(public auth: AuthService) { }
-
- ngOnInit() {
- if (this.auth.userProfile) {
- this.profile = this.auth.userProfile;
- } else {
- this.auth.getProfile((err, profile) => {
- this.profile = profile;
- });
- }
- }
-}
-```
-
-The template for this component looks as follows:
-
-```html
-
-
-
Profile
-
-
-
-
-
-
{{ profile?.nickname }}
-
-
{{ profile | json }}
-
-
-```
-
-## 4. Display UI Elements Conditionally Based on Scope
-
-During the authorization process we already stored the actual scopes which a user was granted in the local storage. If the `scope` returned in the `authResult` is not empty, it means that a user was issued a different set of scopes than what was initially requested, and we should therefore use `authResult.scope` to determine the scopes granted to the user.
-
-If the `scope` returned in `authResult` is issued is empty, it means the user was granted all the scopes that were requested, and we can therefore use the requested scopes to determine the scopes granted to the user.
-
-Here is the code we wroter earlier for the `setSession` function that does that check:
-
-```js
-private setSession(authResult): void {
- // Set the time that the Access Token will expire at
- const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
-
- // If there is a value on the `scope` param from the authResult,
- // use it to set scopes in the session for the user. Otherwise
- // use the scopes as requested. If no scopes were requested,
- // set it to nothing
- const scopes = authResult.scope || this.requestedScopes || '';
-
- localStorage.setItem('access_token', authResult.accessToken);
- localStorage.setItem('id_token', authResult.idToken);
- localStorage.setItem('expires_at', expiresAt);
- localStorage.setItem('scopes', JSON.stringify(scopes));
- this.scheduleRenewal();
-}
-```
-
-Next we need to add a function to the `AuthService` class which we can call to determine if a user was granted a specific scope:
-
-```js
-@Injectable()
-export class AuthService {
- // some code omitted for brevity
-
- public userHasScopes(scopes: Array): boolean {
- const grantedScopes = JSON.parse(localStorage.getItem('scopes')).split(' ');
- return scopes.every(scope => grantedScopes.includes(scope));
- }
-}
-```
-
-You can call this method to determine whether we should display a specific UI element, or not. As an example we only want to display the **Approve Timesheets** link if the user has the `approve:timesheets` scope. Note in the code below that we added a call to the `userHasScopes` function to deteremine whether that link should be displayed or not.
-
-```html
-
-
-
-
-
-```
-
-### Protect a route
-
-We should also protect a route to not allow a route to be navigated to if a user has not been granted the correct scopes. For this we can add a new `ScopeGuardService` service class:
-
-```js
-import { Injectable } from '@angular/core';
-import { Router, CanActivate, ActivatedRouteSnapshot } from '@angular/router';
-import { AuthService } from './auth.service';
-
-@Injectable()
-export class ScopeGuardService implements CanActivate {
-
- constructor(public auth: AuthService, public router: Router) {}
-
- canActivate(route: ActivatedRouteSnapshot): boolean {
-
- const scopes = (route.data as any).expectedScopes;
-
- if (!this.auth.isAuthenticated() || !this.auth.userHasScopes(scopes)) {
- this.router.navigate(['']);
- return false;
- }
- return true;
- }
-
-}
-```
-
-And then use that when we configure the routes to determine whether a route can be activated. Notice the use of the new `ScopeGuardService` in the definition for the `approval` route below:
-
-
-```js
-// app.routes.ts
-
-import { Routes, CanActivate } from '@angular/router';
-import { HomeComponent } from './home/home.component';
-import { ProfileComponent } from './profile/profile.component';
-import { CallbackComponent } from './callback/callback.component';
-import { AuthGuardService as AuthGuard } from './auth/auth-guard.service';
-import { ScopeGuardService as ScopeGuard } from './auth/scope-guard.service';
-import { TimesheetListComponent } from './timesheet-list/timesheet-list.component';
-import { TimesheetAddComponent } from './timesheet-add/timesheet-add.component';
-import { ApprovalComponent } from './approval/approval.component';
-
-export const ROUTES: Routes = [
- { path: '', component: HomeComponent },
- { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
- { path: 'callback', component: CallbackComponent },
- { path: 'timesheets/add', component: TimesheetAddComponent, canActivate: [AuthGuard] },
- { path: 'timesheets', component: TimesheetListComponent, canActivate: [AuthGuard] },
- { path: 'approval', component: ApprovalComponent, canActivate: [ScopeGuard], data: { expectedScopes: ['approve:timesheets']} },
- { path: '**', redirectTo: '' }
-];
-```
-
-## 5. Call the API
-
-The [angular2-jwt](https://github.com/auth0/angular2-jwt) module can be used to automatically attach JSON Web Tokens to requests made to your API. It does this by providing an `AuthHttp` class which is a wrapper over Angular's `Http` class.
-
-Install `angular2-jwt`:
-
-```text
-# installation with npm
-npm install --save angular2-jwt
-
-# installation with yarn
-yarn add angular2-jwt
-```
-
-Create a factory function with some configuration values for `angular2-jwt` and add it to the `providers` array in your application's `@NgModule`. The factory function should have a `tokenGetter` functon which fetches the `access_token` from local storage.
-
-```js
-import { Http, RequestOptions } from '@angular/http';
-import { AuthHttp, AuthConfig } from 'angular2-jwt';
-
-export function authHttpServiceFactory(http: Http, options: RequestOptions) {
- return new AuthHttp(new AuthConfig({
- tokenGetter: (() => localStorage.getItem('access_token'))
- }), http, options);
-}
-
-@NgModule({
- declarations: [...],
- imports: [...],
- providers: [
- AuthService,
- {
- provide: AuthHttp,
- useFactory: authHttpServiceFactory,
- deps: [Http, RequestOptions]
- }
- ],
- bootstrap: [...]
-})
-```
-
-After `angular2-jwt` is configured, you can use the `AuthHttp` class to make secure calls to your API from anywhere in the application. To do so, inject `AuthHttp` in any component or service where it is needed and use it just as you would use Angular's regular `Http` class.
-
-```js
-import { Injectable } from '@angular/core';
-import { Http } from '@angular/http';
-import { AuthHttp } from 'angular2-jwt';
-import 'rxjs/add/operator/map';
-import { NewTimesheetModel } from '../models/new-timesheet-model';
-
-@Injectable()
-export class TimesheetsService {
-
- constructor(public authHttp: AuthHttp) { }
-
- addTimesheet(model: NewTimesheetModel) {
- return this.authHttp.post('http://localhost:8080/timesheets', JSON.stringify(model));
- }
-
- getAllTimesheets() {
- return this.authHttp.get('http://localhost:8080/timesheets')
- .map(res => res.json())
- }
-}
-```
-
-## 6. Renew the Access Token
-
-Renewing the user's `access_token` requires to update the Angular SPA. Add a method to the `AuthService` which calls the `checkSession` method from auth0.js. If the renewal is successful, use the existing `setSession` method to set the new tokens in local storage.
-
-```js
-public renewToken() {
- this.auth0.checkSession({
- audience: AUTH_CONFIG.apiUrl
- }, (err, result) => {
- if (!err) {
- this.setSession(result);
- }
- });
-}
-```
-
-In the `AuthService` class, add a method called `scheduleRenewal` to set up a time at which authentication should be silently renewed. In the sample below this is set up to happen 30 seconds before the actual token expires. Also add a method called `unscheduleRenewal` which will unsubscribe from the Observable.
-
-```js
-public scheduleRenewal() {
- if (!this.isAuthenticated()) return;
-
- const expiresAt = JSON.parse(window.localStorage.getItem('expires_at'));
-
- const source = Observable.of(expiresAt).flatMap(
- expiresAt => {
-
- const now = Date.now();
-
- // Use the delay in a timer to
- // run the refresh at the proper time
- var refreshAt = expiresAt - (1000 * 30); // Refresh 30 seconds before expiry
- return Observable.timer(Math.max(1, refreshAt - now));
- });
-
- // Once the delay time from above is
- // reached, get a new JWT and schedule
- // additional refreshes
- this.refreshSubscription = source.subscribe(() => {
- this.renewToken();
- });
-}
-
-public unscheduleRenewal() {
- if (!this.refreshSubscription) return;
- this.refreshSubscription.unsubscribe();
-}
-```
-
-Finally you need to initiate the schedule renewal. This can be done by calling `scheduleRenewal` inside your `AppComponent` which will happen when the page is loaded. This will occur after every authentication flow, either when the user explicitly logs in, or when the silent authentication happens.
diff --git a/articles/architecture-scenarios/implementations/web-app-sso/implementation-aspnetcore.md b/articles/architecture-scenarios/implementations/web-app-sso/implementation-aspnetcore.md
deleted file mode 100644
index 92856d6d04..0000000000
--- a/articles/architecture-scenarios/implementations/web-app-sso/implementation-aspnetcore.md
+++ /dev/null
@@ -1,177 +0,0 @@
----
-title: "SSO for Regular Web Apps: ASP.NET Core Implementation"
-description: The ASP.NET Core implementation for the SSO for Regular Web Apps architecture scenario
-url: /architecture-scenarios/application/web-app-sso/implementation-aspnetcore
----
-
-# SSO for Regular Web Apps: ASP.NET Core implementation
-
-Full source code for the ASP.NET Core implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-webapp-oidc).
-
-## Configure the Cookie and OIDC Middleware
-
-For the purposes this guide we will be using a simple hosted login. You can use the standard cookie and OIDC middleware which is available with ASP.NET Core, so ensure that you install the NuGet packages.
-
-```text
-Install-Package Microsoft.AspNetCore.Authentication.Cookies
-Install-Package Microsoft.AspNetCore.Authentication.OpenIdConnect
-```
-
-Then configure the cookie and OIDC middleware inside your application's middleware pipeline.
-
-```csharp
-public class Startup
-{
- public void ConfigureServices(IServiceCollection services)
- {
- // Add authentication services
- services.AddAuthentication(
- options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
-
- // Code omitted for brevity...
- }
-
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions auth0Settings)
- {
- // Code omitted for brevity...
-
- // Add the cookie middleware
- app.UseCookieAuthentication(new CookieAuthenticationOptions
- {
- AutomaticAuthenticate = true,
- AutomaticChallenge = true
- });
-
- // Add the OIDC middleware
- app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
- {
- // Set the authority to your Auth0 domain
- Authority = "https://${account.namespace}/",
-
- // Configure the Auth0 Client ID and Client Secret
- ClientId = ${account.clientId},
- ClientSecret = YOUR_CLIENT_SECRET,
-
- // Do not automatically authenticate and challenge
- AutomaticAuthenticate = false,
- AutomaticChallenge = false,
-
- // Set response type to code
- ResponseType = "code",
-
- CallbackPath = new PathString("/signin-auth0"),
-
- // Configure the Claims Issuer to be Auth0
- ClaimsIssuer = "Auth0"
- });
-
- // Code omitted for brevity...
- }
-}
-```
-
-As you can see in the code above, we have configured two different types of authentication middleware.
-
-The first is the cookie middleware which was registered with the call to `UseCookieAuthentication`.
-The second is the OIDC middleware which is done with the call to `UseOpenIdConnectAuthentication`.
-
-Once the user has signed in to Auth0 using the OIDC middleware, their information will automatically be stored inside a session cookie. All you need to do is to configure the middleware as above and it will take care of managing the user session.
-
-The OpenID Connect middleware will also extract all the claims from the `id_token`, which is sent from Auth0 once the user has authenticated, and add them as claims on the `ClaimsIdentity`.
-
-## Implement the Logout
-
-You can control both the application session and the Auth0 session using the `SignOutAsync` method of the `AuthenticationManager` class, and passing along the authentication scheme from which you want to sign out.
-
-As an example to sign out of the cookie middleware, and thereby clearing the authentication cookie for your application, you can make the following call:
-
-```csharp
-await HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
-```
-
-Similarly you can log the user out from Auth0 by making a call to the `SignOutAsync` method and passing along `Auth0` as the authentication scheme to sign out of.
-
-```csharp
-await HttpContext.Authentication.SignOutAsync("Auth0");
-```
-
-For the above to work you will however also need to add extra configuration when registering the OIDC middleware by handling the `OnRedirectToIdentityProviderForSignOut` event. Inside the event you will need to redirect to the [Auth0 logout endpoint](/api/authentication/reference#logout) which will clear the Auth0 cookie.
-
-```csharp
-app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
-{
- // Some code omitted for brevity
- Events = new OpenIdConnectEvents
- {
- OnRedirectToIdentityProviderForSignOut = context =>
- {
- context.Response.Redirect($"https://{auth0Settings.Value.Domain}/v2/logout?client_id={auth0Settings.Value.ClientId}&returnTo={context.Request.Scheme}://{context.Request.Host}/");
- context.HandleResponse();
-
- return Task.FromResult(0);
- }
- }
-});
-```
-
-You will also need to ensure that you add your application's URL to the __Allowed Logout URLs__ for your application inside the Auth0 dashboard. For more information refer to [Logout](/logout).
-
-## Implement Admin permissions
-
-The easiest way to integrate the groups into an ASP.NET Core application is to use the built-in [Role based Authorization](https://docs.asp.net/en/latest/security/authorization/roles.html) available in ASP.NET Core. In order to achieve this we will need to add a Claim of type
-
-```text
-http://schemas.microsoft.com/ws/2008/06/identity/claims/role
-```
-
-for each of the groups a user is assigned to.
-
-Once the claims has been added we can easily ensure that a specific action is available only to `Admin` users by decorating the claim with the `[Authorize(Roles = "Admin")]` attribute. You can also check whether a user is in a specific role from code by making a call to `User.IsInRole("Admin")` from inside your controller.
-
-The ASP.NET OIDC middleware will automatically add all claims returned in the JWT as claims to the `ClaimsIdentity`. We would therefore need to extract the information from the `authorization` claim, deserialize the JSON body of the claim, and for each of the groups add a `http://schemas.microsoft.com/ws/2008/06/identity/claims/role` claim to the `ClaimsIdentity`.
-
-```csharp
-app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
-{
- // Some configuration omitted for brevity
-
- Events = new OpenIdConnectEvents
- {
- OnTicketReceived = context =>
- {
- var options = context.Options as OpenIdConnectOptions;
-
- // Get the ClaimsIdentity
- var identity = context.Principal.Identity as ClaimsIdentity;
- if (identity != null)
- {
- // Add the groups as roles
- var authzClaim = context.Principal.FindFirst(c => c.Type == "authorization");
- if (authzClaim != null)
- {
- var authorization = JsonConvert.DeserializeObject(authzClaim.Value);
- if (authorization != null)
- {
- foreach (var group in authorization.Groups)
- {
- identity.AddClaim(new Claim(ClaimTypes.Role, group, ClaimValueTypes.String, options.Authority));
- }
- }
- }
- }
-
- return Task.FromResult(0);
- }
- }
-});
-```
-
-And subsequently we can add an action which allows Administrators to approve timesheets:
-
-```csharp
-[Authorize(Roles = "Admin")]
-public IActionResult TimesheetApproval()
-{
- return View();
-}
-```
diff --git a/articles/architecture-scenarios/index.md b/articles/architecture-scenarios/index.md
index dd1262cfe7..5f1cf6d905 100644
--- a/articles/architecture-scenarios/index.md
+++ b/articles/architecture-scenarios/index.md
@@ -1,80 +1,78 @@
---
url: /architecture-scenarios
+classes: topic-page
title: Architecture Scenarios
description: Learn about the common architecture scenarios that you will use to solve the authorization and authentication needs of your application.
+topics:
+ - architecture
+ - api-auth
+ - authorization-code
+ - b2c
+ - b2b
+ - ciam
+contentType: index
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+ - implementation
---
-# Architecture Scenarios
+
+
+
+
Architecture Scenarios
+
+ This page describes the typical architecture scenarios we have identified when working with customers on implementing Auth0.
+
+
-This page describes the typical architecture scenarios we have identified when working with customers on implementing Auth0.
+## Application configurations
-Click on any scenario to get more information.
+These scenarios describe the different type of technology architectures your application may use, and how Auth0 can help for each of those.
-## Application Configurations
+The goal of these scenarios is to walk you through the implementation process from beginning to end.
-These scenarios describe the different type of technology architectures your application may use, and how Auth0 can help for each of those.
+
Single-Page Web Application which talks to an API. The application will use OpenID Connect with the Implicit Grant Flow to authenticate users with Auth0.
Mobile Application which talks to an API. The application will use OpenID Connect with the Authorization Code Grant using Proof Key for Code Exchange (PKCE) to authenticate users.
+## Implementation checklists
-## Under Construction
+<%= include('./_includes/_implementation-checklists.md') %>
-These scenarios are under construction and will soon be updated. Some describe the different type of technology architectures your application may use, while others describe the architecture depending on the type of businesses (B2C, B2B, B2E), and how Auth0 can help in each of these scenarios.
+## Implementation resources
-
+Auth0 provides many [resources](/architecture-scenarios/implementation-resources) to help you learn about Auth0, get started quickly, test sample code, and try out APIs.
+
+The Auth0 [Community](https://community.auth0.com) forum and [Blog](https://auth0.com/blog) connect you with the world of Auth0, while our [Support Center](https://support.auth0.com) helps you report issues and manage your subscription. Additionally, you can submit suggested product enhancements through our feedback portal.
+
+We've also made it easy to use our [Status Dashboard](https://status.auth0.com), monitor endpoints, and log data. Notifications keep you up-to-date with Auth0 announcements, and we provide a variety of methods to stay informed about privacy, security, and compliance.
+
+In addition, our [Professional Services](/services) team is available to help you with any architecture needs, including pre-launch advice, production checklists, and operational policies.
diff --git a/articles/architecture-scenarios/application/mobile-api/_stepnav.html b/articles/architecture-scenarios/mobile-api/_stepnav.html
similarity index 100%
rename from articles/architecture-scenarios/application/mobile-api/_stepnav.html
rename to articles/architecture-scenarios/mobile-api/_stepnav.html
diff --git a/articles/architecture-scenarios/mobile-api/api-implementation-nodejs.md b/articles/architecture-scenarios/mobile-api/api-implementation-nodejs.md
new file mode 100644
index 0000000000..7f02afc324
--- /dev/null
+++ b/articles/architecture-scenarios/mobile-api/api-implementation-nodejs.md
@@ -0,0 +1,256 @@
+---
+description: The Node.js implementation of the API for the Mobile + API architecture scenario
+toc: true
+topics:
+ - mobile-apps
+ - api-auth
+ - nodejs
+ - architecture
+ - authorization-code
+ - pkce
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - enable-mobile-auth
+ - build-an-app
+---
+
+# Mobile + API: Node.js Implementation for the API
+
+This document is part of the [Mobile + API Architecture Scenario](/architecture-scenarios/application/mobile-api) and it explains how to implement the API in Node.js. Please refer to the scenario for information on the implemented solution.
+
+::: note
+The full source code for the Node.js API implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).
+:::
+
+## 1. Define the API endpoints
+
+We will use the [Express web application framework](http://expressjs.com/) to build our Node.js API.
+
+### Create a package.json File
+
+Create a folder for your API, navigate into it and run `npm init`. This will setup your `package.json` file.
+
+You can leave the default settings or change them as you see fit.
+
+Our sample's `package.json` looks like the following:
+
+```json
+{
+ "name": "timesheets-api",
+ "version": "1.0.0",
+ "description": "API used to add timesheet entries for employees and contractors",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
+ },
+ "author": "Auth0",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
+ },
+ "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
+}
+```
+
+### Install the Dependencies
+
+Next, we need to set our dependencies. We will use the following modules:
+
+- **express**: This module adds the [Express web application framework](https://expressjs.com/).
+
+- **cors**: This module adds support for enabling [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) which is required since the API will be called from a Single-Page Application running on a different domain inside a web browser.
+
+- **jwks-rsa**: This library retrieves RSA signing keys from a **JWKS** (JSON Web Key Set) endpoint. Using `expressJwtSecret` we can generate a secret provider that will provide the right signing key to `express-jwt` based on the `kid` in the JWT header. For more information refer to the [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
+
+- **express-jwt**: This module lets you authenticate HTTP requests using JWT tokens in your Node.js applications. It provides several functions that make working with JWTs easier. For more information refer to the [express-jwt GitHub repository](https://github.com/auth0/express-jwt).
+
+- **body-parser**: This is a Node.js body parsing middleware. It extracts the entire body portion of an incoming request stream and exposes it on `req.body` as something easier to interface with.For more information and several alternatives refer to the body-parser GitHub repository.
+
+To install these dependencies run the following:
+
+```bash
+npm install express cors express-jwt jwks-rsa body-parser express-jwt-authz --save
+```
+
+### Implement the Endpoints
+
+Navigate to your API directory and create a `server.js` file. Your code needs to:
+
+- Get the dependencies.
+- Implement the endpoint(s).
+- Launch the API server.
+
+This is our sample implementation:
+
+```js
+const express = require('express');
+const app = express();
+const jwt = require('express-jwt');
+const jwksRsa = require('jwks-rsa');
+const cors = require('cors');
+const bodyParser = require('body-parser');
+
+// Enable CORS
+app.use(cors());
+
+// Enable the use of request body parsing middleware
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({
+ extended: true
+}));
+
+// Create timesheets API endpoint
+app.post('/timesheets', function(req, res){
+ res.status(201).send({message: "This is the POST /timesheets endpoint"});
+})
+
+// Launch the API Server at localhost:8080
+app.listen(8080);
+```
+
+Launch your API server using `node server` and make an HTTP POST request to `localhost:8080/timesheets`. You should see a JSON response with the message `This is the POST /timesheets endpoint`.
+
+So now we have our endpoint but anyone can call it. Continue to the next paragraph to see how we can fix this.
+
+## 2. Secure the API endpoints
+
+In order to validate our token we will use the `jwt` function, provided by the [express-jwt middleware](https://github.com/auth0/express-jwt#usage), and the `jwks-rsa` to retrieve our secret. The libraries do the following:
+
+1. `express-jwt` will decode the token and pass the request, the header and the payload to `jwksRsa.expressJwtSecret`.
+
+1. `jwks-rsa` will then download all signing keys from the JWKS endpoint and see if a one of the signing keys matches the `kid` in the header of the JWT. If none of the signing keys match the incoming `kid`, an error will be thrown. If we have a match, we will pass the right signing key to `express-jwt`.
+
+1. `express-jwt` will the continue its own logic to validate the signature of the token, the expiration, `audience` and the `issuer`.
+
+The steps we will follow in our code are:
+
+- Create the middleware function to validate the Access Token.
+- Enable the use of the middleware in our routes.
+
+You can also write some code to actually save the timesheet to a database. This is our sample implementation (some code is omitted for brevity):
+
+```js
+// set dependencies - code omitted
+
+// Enable CORS - code omitted
+
+// Create middleware for checking the JWT
+const checkJwt = jwt({
+ // Dynamically provide a signing key based on the kid in the header and the signing keys provided by the JWKS endpoint
+ secret: jwksRsa.expressJwtSecret({
+ cache: true,
+ rateLimit: true,
+ jwksRequestsPerMinute: 5,
+ jwksUri: `https://${account.namespace}/.well-known/jwks.json`
+ }),
+
+ // Validate the audience and the issuer
+ audience: '{YOUR_API_IDENTIFIER}', //replace with your API's audience, available at Dashboard > APIs
+ issuer: 'https://${account.namespace}/',
+ algorithms: [ 'RS256' ]
+});
+
+// Enable the use of request body parsing middleware - code omitted
+
+// create timesheets API endpoint - code omitted
+app.post('/timesheets', checkJwt, function(req, res){
+ var timesheet = req.body;
+
+ // Save the timesheet to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+});
+// launch the API Server at localhost:8080 - code omitted
+```
+
+If we launch our server now and do an HTTP POST to `localhost:8080/timesheets` we should get the error message `Missing or invalid token` (which is perfectly fine since we didn’t send an Access Token in our request).
+
+In order to test the working scenario as well we need to:
+
+- Get an Access Token. For details on how to do so refer to: [Get an Access Token](/architecture-scenarios/application/server-api#get-an-access-token).
+- Invoke the API while adding an `Authorization` header to our request with the value `Bearer ACCESS_TOKEN` (where *ACCESS_TOKEN* is the value of the token we retrieved in the first step).
+
+## 3. Check the application permissions
+
+In this step we will add to our implementation the ability to check if the application has permissions (or `scope`) to use our endpoint in order to create a timesheet. In particular we want to ensure that the token has the correct scope, which is `batch:upload`.
+
+In order to do this we will make use of the `express-jwt-authz` Node.js package, so go ahead and add that to your project:
+
+```bash
+npm install express-jwt-authz --save
+```
+
+Now it is as simple as adding a call to `jwtAuthz(...)` to your middleware to ensure that the JWT contain a particular scope in order to execute a particular endpoint.
+
+We will add an additional dependency. The **express-jwt-authz** library, which is used in conjunction with express-jwt, validates the [JWT](/tokens/concepts/jwts) and ensures it bears the correct permissions to call the desired endpoint. For more information refer to the [express-jwt-authz GitHub repository](https://github.com/auth0/express-jwt-authz).
+
+This is our sample implementation (some code is omitted for brevity):
+
+```js
+// set dependencies - some code omitted
+const jwtAuthz = require('express-jwt-authz');
+
+// Enable CORS - code omitted
+
+// Create middleware for checking the JWT - code omitted
+
+// Enable the use of request body parsing middleware - code omitted
+
+// create timesheets API endpoint
+app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets']), function(req, res){
+ var timesheet = req.body;
+
+ // Save the timesheet to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+})
+
+// launch the API Server at localhost:8080 - code omitted
+```
+
+If we invoke our API with a token that does not include this scope we should get the error message Forbidden with the HTTP status code `403`. You can test this by removing this scope from your API.
+
+## 4. Determine the User Identity
+
+The `express-jwt` middleware which is used to validate the JWT, also sets the `req.user` with the information contained in the JWT. If you want to use the `sub` claim to identify the user uniquely, you can simply use `req.user.sub`.
+
+In the case of the timesheets application however, we want to use the email address of the user as the unique identifier.
+
+The first thing we need to do is to write a rule which will add the email address of the user to the Access Token. Go to the [Rules section](${manage_url}/#/rules}) of the Dashboard and click on the __Create Rule__ button.
+
+You can give the rule a descriptive name, for example `Add email to Access Token`, and then use the following code for the rule:
+
+```js
+function (user, context, callback) {
+ const namespace = 'https://api.exampleco.com/';
+ context.accessToken[namespace + 'email'] = user.email;
+ callback(null, user, context);
+}
+```
+
+The `namespace` is used to ensure the claim has a unique name and does not clash with the names of any of the standard OIDC claims. For more info on namespaced claims, see [Namespacing Claims](/tokens/guides/create-namespaced-custom-claims).
+
+Next, inside your API, you can retrieve the value of the claim from `req.user`, and use that as the unique user identity which you can associate with timesheet entries.
+
+```js
+app.get('/timesheets', checkJwt, jwtAuthz(['read:timesheets']), function(req, res) {
+ var timesheet = req.body;
+
+ // Associate the timesheet entry with the current user
+ var userId = req.user['https://api.exampleco.com/email'];
+ timesheet.user_id = userId;
+
+ // Save the timesheet to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+});
+```
diff --git a/articles/architecture-scenarios/mobile-api/index.md b/articles/architecture-scenarios/mobile-api/index.md
new file mode 100644
index 0000000000..c96949af52
--- /dev/null
+++ b/articles/architecture-scenarios/mobile-api/index.md
@@ -0,0 +1,60 @@
+---
+order: 04
+title: Mobile + API
+image: /media/articles/architecture-scenarios/mobile-api.png
+extract: Mobile application which talks to an API. The application will use OpenID Connect (OIDC) with the Authorization Code Grant using Proof Key for Code Exchange (PKCE) to authenticate users.
+description: Explains the architecture scenario with a mobile application communicating with an API.
+toc: true
+topics:
+ - architecture
+ - mobile-apps
+ - api-auth
+ - authorization-code
+ - pkce
+contentType:
+ - index
+ - tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - enable-mobile-auth
+ - build-an-app
+---
+
+# Mobile + API
+
+In this scenario we will build a Timesheet API for a fictitious company named ExampleCo. The API will allow management of timesheet entries for an employee or a contractor.
+
+We will also be building a mobile application which will be used to view and log timesheet entries in the centralized timesheet database using the API.
+
+
+::: panel TL;DR
+* Auth0 provides API Authentication and Authorization as a means to secure access to API endpoints (see [API Authentication and Authorization](/architecture-scenarios/mobile-api/part-1#api-authentication-and-authorization))
+* For authorizing a mobile app user and granting access to the API, Auth0 supports the [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce) (see [Proof Key for Code Exchange](/architecture-scenarios/mobile-api/part-1#proof-key-for-code-exchange-pkce-))
+* Both the mobile app and the API must be configured in the Auth0 Dashboard (see [Auth0 Configuration](/architecture-scenarios/mobile-api/part-2))
+* User Permissions can be enforced using the Authorization Extension (see [Configure the Authorization Extension](/architecture-scenarios/mobile-api/part-2#configure-the-authorization-extension))
+* The API is secured by ensuring that a valid [Access Token](/tokens/concepts/access-tokens) is passed in the HTTP Authorization header when calls are made to the API (see [Implement the API](/architecture-scenarios/mobile-api/part-3#secure-the-endpoints))
+* The Auth0.Android SDK can be used to authorize the user of the mobile app and obtain a valid Access Token which can be used to call the API (see [Authorize the User](/architecture-scenarios/mobile-api/part-3#authorize-the-user))
+* The mobile app can retrieve the user's profile information by decoding the ID Token (see [Get the User Profile](/architecture-scenarios/mobile-api/part-3#get-the-user-profile))
+* UI Elements can be displayed conditionally based on the scope that was granted to the user (see [Display UI Elements Conditionally Based on Scope](/architecture-scenarios/mobile-api/part-3#display-ui-elements-conditionally-based-on-scope))
+* The mobile app provides the Access Token in the HTTP Authorization header when making calls to the API (see [Call the API](/architecture-scenarios/mobile-api/part-3#call-the-api))
+* The mobile app user's Access Token can be renewed to ensure the user does not have to log in again during a session (see [Renew the Token](/architecture-scenarios/mobile-api/part-3#renew-the-token))
+:::
+
+## The Premise
+
+ExampleCo is a consulting startup company. Currently they have approximately 100 employees and they also outsource several activities to external contractors. All employees and external contractors are required to fill in their timesheets every week.
+
+The company has built a timesheets application, a scenario we covered in [Single Sign-On for Regular Web Apps](/architecture-scenarios/application/web-app-sso). The internal employees use this web app to fill in their timesheets, but the company wants a mobile application for employees and contractors to use while not on the premises. The app will be used to log timesheet entries and send the data to the centralized timesheet database using the API. The app will also allow managers to approve timesheet entries.
+
+### Goals & Requirements
+
+ExampleCo wants to build a flexible solution. There are potential multiple employees and contractors who should be able to log timesheet entries, as well as batch processes which may upload timesheet entries from other, external systems.
+
+Hence the company has decided to develop a single Timesheets API which will be used to log time not only by this mobile app, but by all other apps as well. They want to put in place a security architecture that is flexible enough to accommodate this. ExampleCo wants to ensure that a large part of the code and business logic for the application can be shared across the different applications.
+
+It is required that only authorized users and applications are allowed access to the Timesheets API.
+
+<%= include('./_stepnav', {
+ next: ["1. Solution Overview", "/architecture-scenarios/mobile-api/part-1"]
+}) %>
diff --git a/articles/architecture-scenarios/mobile-api/mobile-implementation-android.md b/articles/architecture-scenarios/mobile-api/mobile-implementation-android.md
new file mode 100644
index 0000000000..13dabfaf1c
--- /dev/null
+++ b/articles/architecture-scenarios/mobile-api/mobile-implementation-android.md
@@ -0,0 +1,1418 @@
+---
+description: The Android implementation of the API for the Mobile + API architecture scenario
+toc: true
+topics:
+ - mobile-apps
+ - api-auth
+ - android
+ - architecture
+ - authorization-code
+ - pkce
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - enable-mobile-auth
+ - build-an-app
+---
+
+# Mobile + API: Android Implementation for the Mobile App
+
+This document is part of the [Mobile + API Architecture Scenario](/architecture-scenarios/application/mobile-api) and it explains how to implement the mobile application in Android. Please refer to the scenario for information on the implemented solution.
+
+## 1. Set Up the Application
+
+<%= include('../../_includes/_package', {
+ org: 'auth0-samples',
+ repo: 'auth0-pnp-exampleco-timesheets',
+ path: 'timesheets-mobile/android',
+ requirements: [
+ 'Android Studio 2.3',
+ 'Android SDK 25',
+ 'Emulator - Nexus 5X - Android 6.0'
+ ]
+}) %>
+
+### Set the Dependencies
+
+For this implementation, we will use the following dependencies within the app’s `build.gradle` file:
+
+- [Auth0.Android](https://github.com/auth0/Auth0.Android): this package enables integration with Auth0 to authenticate users.
+- [OkHttp](http://square.github.io/okhttp/): this package provides an HTTP application to make requests to the Node.JS API.
+- [JWTDecode.Android](https://github.com/auth0/JWTDecode.Android): this package will assist with decoding JWTs.
+- AppCompat: this package lets us use the toolbar widget for navigation in our activities.
+
+```gradle
+dependencies {
+ compile 'com.squareup.okhttp:okhttp:2.7.5'
+ compile 'com.auth0.android:auth0:1.10.0'
+ compile 'com.auth0.android:jwtdecode:1.1.1'
+ compile 'com.android.support:appcompat-v7:25.3.1'
+ testCompile 'junit:junit:4.12'
+}
+```
+
+### Update the Manifest
+
+Open the application's `AndroidManifest.xml` and add the internet permission:
+
+```xml
+
+```
+
+We’ll also update the application details to utilize the Toolbar widget:
+
+```xml
+
+
+```
+
+### Set Configuration Values
+
+Set your Auth0 Client ID, Auth0 Domain, and API’s url in the `strings.xml` resource located in `/res/values/strings.xml`:
+
+```xml
+
+ ExampleCo Timesheets
+ Log in
+ ...
+ ...
+ http://10.0.2.2:8080/timesheets
+
+```
+
+### Create Package Structure
+
+For this implementation, create directories for activities, models, and utils in the application package.
+
+- `activities/`: this package will contain the `LoginActivity.java`, `TimeSheetActivity.java`, `FormActivity.java`, and `UserActivity.java`.
+- `models/`: this package will contain the `TimeSheet.java` and `User.java` data models.
+- `utils/`: this package will contain the `UserProfileManager.java`, `TimeSheetAdapter.java`, and `ImageTask.java`
+
+## 2. Authorize the User
+
+### Update the Manifest
+
+Open the app's `AndroidManifest.xml` and add the `LoginActivity`:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Create the Login Activity Layout
+
+Next create `login_activity.xml`, the layout for the `LoginActivity`:
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+### Create the Login Activity
+
+The `LoginActivity` will handle user authorization and be the initial screen users see. We'll create a `login()` method to initialize a `WebAuthProvider` and start authentication. Ensure you provide the correct scheme, audience, and scope to the `WebAuthProvider`. For this implementation we will use:
+
+- __scheme__: `demo`
+- __audience__: `https://api.exampleco.com/timesheets` (the Node.JS API)
+- __response_type__: `code`
+- __scope__: `create:timesheets read:timesheets openid profile email offline_access`. These scopes will enable us to `POST` and `GET` to the Node.JS API, as well as retrieve the user profile and a Refresh Token.
+
+```java
+private void login() {
+ Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
+ auth0.setOIDCConformant(true);
+
+ WebAuthProvider.init(auth0)
+ .withScheme("demo")
+ .withAudience("https://api.exampleco.com/timesheets")
+ .withResponseType(ResponseType.CODE)
+ .withScope("create:timesheets read:timesheets openid profile email offline_access")
+ .start(
+ // ...
+ );
+}
+```
+
+In the `login()` method, upon successful authentication we'll redirect the user to the `TimeSheetActivity`.
+
+```java
+package com.auth0.samples.activities;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+import com.auth0.android.Auth0;
+import com.auth0.android.authentication.AuthenticationException;
+import com.auth0.android.jwt.JWT;
+import com.auth0.android.provider.AuthCallback;
+import com.auth0.android.provider.ResponseType;
+import com.auth0.android.provider.WebAuthProvider;
+import com.auth0.android.result.Credentials;
+import com.auth0.samples.R;
+import com.auth0.samples.models.User;
+import com.auth0.samples.utils.CredentialsManager;
+import com.auth0.samples.utils.UserProfileManager;
+
+public class LoginActivity extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.login_activity);
+ Button loginWithTokenButton = (Button) findViewById(R.id.loginButton);
+ loginWithTokenButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ login();
+ }
+ });
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ if (WebAuthProvider.resume(intent)) {
+ return;
+ }
+ super.onNewIntent(intent);
+ }
+
+ private void login() {
+ Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
+ auth0.setOIDCConformant(true);
+
+ WebAuthProvider.init(auth0)
+ .withScheme("demo")
+ .withAudience("https://api.exampleco.com/timesheets")
+ .withResponseType(ResponseType.CODE)
+ .withScope("create:timesheets read:timesheets openid profile email")
+ .start(LoginActivity.this, new AuthCallback() {
+ @Override
+ public void onFailure(@NonNull final Dialog dialog) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ dialog.show();
+ }
+ });
+ }
+
+ @Override
+ public void onFailure(final AuthenticationException exception) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(LoginActivity.this, "Error: " + exception.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ @Override
+ public void onSuccess(@NonNull final Credentials credentials) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
+ }
+ });
+ startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
+ }
+ });
+ }
+}
+```
+
+### Store the Credentials
+
+To store the credentials received after login, we’ll use the `CredentialsManager` from the Auth0.Android library and [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences.html) for storage.
+
+Before initializing the `WebAuthProvider` in the `login()` method, we can create the `CredentialsManager`. Passing an `AuthenticationAPIClient` to the `CredentialsManager` enables it to refresh the Access Tokens if they are expired.
+
+```java
+private void login() {
+ Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
+ auth0.setOIDCConformant(true);
+
+ AuthenticationAPIClient authAPIClient = new AuthenticationAPIClient(auth0);
+ SharedPreferencesStorage sharedPrefStorage = new SharedPreferencesStorage(this);
+ final CredentialsManager credentialsManager = new CredentialsManager(authAPIClient, sharedPrefStorage);
+
+ WebAuthProvider.init(auth0)
+ // ...
+ }
+```
+
+Now update the `login()` method so that credentials are stored via the `CredentialsManager` after a successful authentication.
+
+```java
+// ...
+@Override
+public void onSuccess(@NonNull final Credentials credentials) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ credentialsManager.saveCredentials(credentials);
+ startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
+// ...
+}
+```
+
+## 3. Get the User Profile
+
+### Create the User Model
+
+Create a simple User model that will be utilized by the `UserProfileManager` and `UserActivity`.
+
+```java
+package com.auth0.samples.models;
+
+public class User {
+ private String email;
+ private String name;
+ private String pictureURL;
+
+ public User(String email, String name, String pictureURL) {
+ this.email = email;
+ this.name = name;
+ this.pictureURL = pictureURL;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPictureURL() {
+ return pictureURL;
+ }
+}
+
+```
+
+### Store the User Profile
+
+To handle storing user profile information we'll create a manager class `UserProfileManager`. The `UserProfileManager` will use [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences.html) to store data.
+
+```java
+package com.auth0.samples.utils;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.auth0.android.result.UserProfile;
+import com.auth0.samples.models.User;
+
+public class UserProfileManager {
+
+ private static final String PREFERENCES_NAME = "auth0_user_profile";
+ private static final String EMAIL = "email";
+ private static final String NAME = "name";
+ private static final String PICTURE_URL = "picture_url";
+
+ public static void saveUserInfo(Context context, User userInfo) {
+ SharedPreferences sp = context.getSharedPreferences(
+ PREFERENCES_NAME, Context.MODE_PRIVATE);
+
+ sp.edit()
+ .putString(EMAIL, userInfo.getEmail())
+ .putString(NAME, userInfo.getName())
+ .putString(PICTURE_URL, userInfo.getPictureURL())
+ .apply();
+ }
+
+ public static User getUserInfo(Context context) {
+ SharedPreferences sp = context.getSharedPreferences(
+ PREFERENCES_NAME, Context.MODE_PRIVATE);
+
+ return new User(
+ sp.getString(EMAIL, null),
+ sp.getString(NAME, null),
+ sp.getString(PICTURE_URL, null)
+ );
+ }
+
+ public static void deleteUserInfo(Context context) {
+ SharedPreferences sp = context.getSharedPreferences(
+ PREFERENCES_NAME, Context.MODE_PRIVATE);
+
+ sp.edit()
+ .putString(EMAIL, null)
+ .putString(NAME, null)
+ .putString(PICTURE_URL, null)
+ .apply();
+ }
+}
+```
+
+Next, update the `login()` method in the `LoginActivity` to retrieve the ID Token and get the user profile from the token with the JWTDecode.Android library. Then store the user profile with the `UserProfileManager`.
+
+```java
+// ...
+@Override
+public void onSuccess(@NonNull final Credentials credentials) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ credentialsManager.saveCredentials(credentials);
+ JWT jwt = new JWT(credentials.getIdToken());
+ User user = new User(
+ jwt.getClaim("email").asString(),
+ jwt.getClaim("name").asString(),
+ jwt.getClaim("picture").asString()
+ );
+ UserProfileManager.saveUserInfo(LoginActivity.this, user);
+
+ startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
+}
+// ...
+```
+
+## 4. Display UI Elements Conditionally Based on Scope
+
+To determine whether a user has permissions to perform certain actions, we can look at the `scope` that was granted to the user during the authentication process. The `scope` will contain a string with all the scopes granted to a user, so to determine whether a particular scope was granted, we simply need to look whether the string of scopes contain the substring for that particular scope.
+
+### Store the Scope
+
+First, we can update the `User` class to store the granted scopes, and then provide a helper method, `hasScope()` which can be used to determine whether the granted scopes contain a particular scope:
+
+```java
+public class User {
+ private String email;
+ private String name;
+ private String pictureURL;
+ private String grantedScope;
+
+ public User(String email, String name, String pictureURL, String grantedScope) {
+ this.email = email;
+ this.name = name;
+ this.pictureURL = pictureURL;
+ this.grantedScope = grantedScope;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getGrantedScope() {
+ return grantedScope;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPictureURL() {
+ return pictureURL;
+ }
+
+ public Boolean hasScope(String scope) {
+ return grantedScope.contains(scope);
+ }
+}
+```
+
+Also remember to update the `UserProfileManager` to store the extra field:
+
+```java
+public class UserProfileManager {
+
+ private static final String PREFERENCES_NAME = "auth0_user_profile";
+ private static final String EMAIL = "email";
+ private static final String NAME = "name";
+ private static final String PICTURE_URL = "picture_url";
+ private static final String SCOPE = "scope";
+
+ public static void saveUserInfo(Context context, User userInfo) {
+ SharedPreferences sp = context.getSharedPreferences(
+ PREFERENCES_NAME, Context.MODE_PRIVATE);
+
+ sp.edit()
+ .putString(EMAIL, userInfo.getEmail())
+ .putString(NAME, userInfo.getName())
+ .putString(PICTURE_URL, userInfo.getPictureURL())
+ .putString(SCOPE, userInfo.getGrantedScope())
+ .apply();
+ }
+
+ public static User getUserInfo(Context context) {
+ SharedPreferences sp = context.getSharedPreferences(
+ PREFERENCES_NAME, Context.MODE_PRIVATE);
+
+ return new User(
+ sp.getString(EMAIL, null),
+ sp.getString(NAME, null),
+ sp.getString(PICTURE_URL, null),
+ sp.getString(SCOPE, null)
+ );
+ }
+
+ public static void deleteUserInfo(Context context) {
+ SharedPreferences sp = context.getSharedPreferences(
+ PREFERENCES_NAME, Context.MODE_PRIVATE);
+
+ sp.edit()
+ .putString(EMAIL, null)
+ .putString(NAME, null)
+ .putString(PICTURE_URL, null)
+ .putString(SCOPE, null)
+ .apply();
+ }
+}
+```
+
+Next, update the `LoginActivity` to pass along the `scope` so it can be stored in the `User` object:
+
+```java
+// ...
+@Override
+public void onSuccess(@NonNull final Credentials credentials) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(LoginActivity.this, "Log In - Success", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ credentialsManager.saveCredentials(credentials);
+ JWT jwt = new JWT(credentials.getIdToken());
+ String scopes = credentials.getScope();
+ User user = new User(
+ jwt.getClaim("email").asString(),
+ jwt.getClaim("name").asString(),
+ jwt.getClaim("picture").asString(),
+ credentials.getScope()
+ );
+ UserProfileManager.saveUserInfo(LoginActivity.this, user);
+
+ startActivity(new Intent(LoginActivity.this, TimeSheetActivity.class));
+}
+// ...
+```
+
+### Display Approval Menu Based on Scope
+
+Now, we can display certain UI elements based on whether the user was granted a particular scope. As an example, we have an approval menu item which should only be visible to users who have been granted the `approve:timesheets` scope.
+
+Below you can see the code from the `BaseActivity` class which checks whether a user has the `approve:timesheets` scope, and based on that will set the visibility of the menu item which displays the approval activity:
+
+```java
+// ...
+@Override
+public boolean onCreateOptionsMenu(Menu menu) {
+ Boolean canApprove = UserProfileManager.getUserInfo(this).hasScope("approve:timesheets");
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.actions, menu);
+ MenuItem item = menu.findItem(R.id.action_approve);
+ item.setVisible(canApprove);
+ return super.onCreateOptionsMenu(menu);
+}
+// ...
+```
+
+## 5. Call the API
+
+### Update the Manifest
+
+Open the app's `AndroidManifest.xml` and add the `TimeSheetActivity`:
+
+```xml
+
+```
+
+### Create the Timesheets Activity Layouts
+
+Next create `timesheet_activity.xml`, the layout for the `TimeSheetsActivity`:
+
+```xml
+
+
+
+
+
+
+
+```
+
+The `ListView` widget will contain individual entries which are represented by the `item_entry.xml` layout:
+
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+And for the Toolbar navigation on the `TimeSheetActivity`, we’ll create the `timesheet_action_menu.xml` menu resource (`/res/menu/`):
+
+```xml
+
+
+```
+
+### Create the Timesheet Model
+
+Create a model for working with timesheet data in our views:
+
+```java
+package com.auth0.samples.models;
+
+import java.util.Date;
+
+/**
+ * Created by ej on 7/9/17.
+ */
+
+public class TimeSheet {
+ private String userID;
+ private String projectName;
+ private String date;
+ private double hours;
+ private int ID;
+
+ public TimeSheet(String gUserID, String gProjectName, String gDate, double gHours, int gID) {
+ this.userID = gUserID;
+ this.projectName = gProjectName;
+ this.date = gDate;
+ this.hours = gHours;
+ this.ID = gID;
+ }
+
+ public String getUserID() {
+ return userID;
+ }
+
+ public String getProjectName() {
+ return projectName;
+ }
+
+ public String getDateString() {
+ return date;
+ }
+
+ public double getHours() {
+ return hours;
+ }
+
+ public int getID() {
+ return ID;
+ }
+}
+```
+
+### Create the Timesheet Adapter
+
+The `TimeSheetAdapter` is a utility class which will take an array of timesheet entries and apply them to the `ListView` on the `TimeSheetActivity`.
+
+```java
+package com.auth0.samples.utils;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+import com.auth0.samples.R;
+import com.auth0.samples.models.TimeSheet;
+import java.util.ArrayList;
+
+public class TimeSheetAdapter extends ArrayAdapter {
+
+ public TimeSheetAdapter(Context context, ArrayList timesheets) {
+ super(context, 0, timesheets);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+
+ TimeSheet timesheet = getItem(position);
+
+ if (convertView == null) {
+ convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_entry, parent, false);
+ }
+
+ TextView tvUserID = (TextView) convertView.findViewById(R.id.tvUserID);
+ TextView tvDate = (TextView) convertView.findViewById(R.id.tvDate);
+ TextView tvProjectName = (TextView) convertView.findViewById(R.id.tvProjectName);
+ TextView tvHours = (TextView) convertView.findViewById(R.id.tvHours);
+
+ tvUserID.setText(timesheet.getUserID());
+ tvDate.setText(timesheet.getDateString());
+ tvProjectName.setText(timesheet.getProjectName());
+ tvHours.setText(Double.toString(timesheet.getHours()));
+
+ return convertView;
+ }
+}
+```
+
+### Create the Timesheet Activity
+
+The `TimeSheetActivity` displays the timesheet entries for the logged in user which are stored on the server.
+
+- The `@string/api_url` is set to `http://10.0.2.2:8080/timesheets` so the Android Emulator can connect to the Node.JS API running on `http://localhost:8080`.
+- The `callAPI()` method retrieves timesheets from the Node.JS API.
+- The `processResults()` method takes the JSON response from `callAPI()` and converts it `TimeSheet` objects.
+- The `onCreateOptionsMenu()` and `onOptionsItemSelected()` methods handle the Toolbar widget navigation functionality.
+
+```java
+package com.auth0.samples.activities;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import com.auth0.android.Auth0;
+import com.auth0.android.authentication.AuthenticationAPIClient;
+import com.auth0.android.authentication.storage.CredentialsManager;
+import com.auth0.android.authentication.storage.CredentialsManagerException;
+import com.auth0.android.authentication.storage.SharedPreferencesStorage;
+import com.auth0.android.callback.BaseCallback;
+import com.auth0.android.result.Credentials;
+import com.auth0.samples.R;
+import com.auth0.samples.utils.TimeSheetAdapter;
+import com.auth0.samples.models.TimeSheet;
+import com.squareup.okhttp.Callback;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class TimeSheetActivity extends AppCompatActivity {
+
+ private ArrayList timesheets = new ArrayList<>();
+
+ private String accessToken;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.timesheet_activity);
+ Toolbar navToolbar = (Toolbar) findViewById(R.id.navToolbar);
+ setSupportActionBar(navToolbar);
+
+ Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
+ auth0.setOIDCConformant(true);
+
+ AuthenticationAPIClient authAPIClient = new AuthenticationAPIClient(auth0);
+ SharedPreferencesStorage sharedPrefStorage = new SharedPreferencesStorage(this);
+
+ CredentialsManager credentialsManager = new CredentialsManager(authAPIClient, sharedPrefStorage);
+ credentialsManager.getCredentials(new BaseCallback() {
+ @Override
+ public void onSuccess(Credentials payload) {
+ accessToken = payload.getAccessToken();
+ callAPI();
+ }
+
+ @Override
+ public void onFailure(CredentialsManagerException error) {
+ Toast.makeText(TimeSheetActivity.this, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ private void callAPI() {
+ final Request.Builder reqBuilder = new Request.Builder()
+ .get()
+ .url(getString(R.string.api_url))
+ .addHeader("Authorization", "Bearer " + accessToken);
+
+ OkHttpClient client = new OkHttpClient();
+ Request request = reqBuilder.build();
+ client.newCall(request).enqueue(new Callback() {
+ @Override
+ public void onFailure(Request request, IOException e) {
+ Log.e("API", "Error: ", e);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(TimeSheetActivity.this, "An error occurred", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ @Override
+ public void onResponse(final Response response) throws IOException {
+ timesheets = processResults(response);
+ final TimeSheetAdapter adapter = new TimeSheetAdapter(TimeSheetActivity.this, timesheets);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (response.isSuccessful()) {
+ ListView listView = (ListView) findViewById(R.id.timesheetList);
+ listView.setAdapter(adapter);
+ adapter.addAll(timesheets);
+ } else {
+ Toast.makeText(TimeSheetActivity.this, "API call failed.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+ });
+ }
+
+ private ArrayList processResults (Response response) {
+ ArrayList timesheets = new ArrayList<>();
+ try {
+ String jsonData = response.body().string();
+ if (response.isSuccessful()) {
+ JSONArray timesheetJSONArray = new JSONArray(jsonData);
+ for (int i = 0; i < timesheetJSONArray.length(); i++) {
+ JSONObject timesheetJSON = timesheetJSONArray.getJSONObject(i);
+ String userID = timesheetJSON.getString("user_id");
+ String projectName = timesheetJSON.getString("project");
+ String dateStr = timesheetJSON.getString("date");
+ Double hours = timesheetJSON.getDouble("hours");
+ int id = timesheetJSON.getInt("id");
+
+ TimeSheet timesheet = new TimeSheet(userID, projectName, dateStr, hours, id);
+ timesheets.add(timesheet);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return timesheets;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.timesheet_action_menu, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_new:
+ startActivity(new Intent(TimeSheetActivity.this, FormActivity.class));
+ break;
+ case R.id.action_profile:
+ startActivity(new Intent(TimeSheetActivity.this, UserActivity.class));
+ break;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ return true;
+ }
+}
+```
+
+## 6. View the User Profile
+
+To display the logged in user’s profile we’ll create the `UserActivity`, a corresponding `user_activity.xml` layout, and the `user_action_menu.xml` for the Toolbar navigation. The view will display the user’s name, email, and profile picture.
+
+### Update the Manifest
+
+Open the app's `AndroidManifest.xml` and add the `UserActivity`:
+
+```xml
+
+```
+
+#### Create the User Activity Layouts
+
+Next create `user_activity.xml`, the layout for the `UserActivity`, with an `ImageView` for the profile picture and `TextViews` for the user's name and email.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+```
+
+And create the `user_actions_menu.xml` for the `UserActivity` Toolbar:
+
+```xml
+
+
+```
+
+### Load the Profile Picture from URL
+
+In order to load the user profile picture from the URL, create a task which extends `AsyncTask` and executes in the background.
+
+```java
+package com.auth0.samples.utils;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.AsyncTask;
+import android.util.Log;
+import android.widget.ImageView;
+
+import java.io.InputStream;
+import java.net.URL;
+
+public class ImageTask extends AsyncTask {
+
+ private ImageView bmImage;
+
+ public ImageTask(ImageView bmImage) {
+ this.bmImage = bmImage;
+ }
+
+ protected Bitmap doInBackground(String... urls) {
+ String urldisplay = urls[0];
+ Bitmap mIcon11 = null;
+
+ try {
+ InputStream in = new URL(urldisplay).openStream();
+ mIcon11 = BitmapFactory.decodeStream(in);
+ } catch (Exception e) {
+ Log.e("Error", e.getMessage());
+ e.printStackTrace();
+ }
+ return mIcon11;
+ }
+
+ protected void onPostExecute(Bitmap result) {
+ bmImage.setImageBitmap(result);
+ }
+}
+```
+
+### Create the User Activity
+
+In the `onCreate()` method we'll retrieve the user information from the `UserProfileManager` and set the values in the view. As before, the `onCreateOptionsMenu()` and `onOptionsItemSelected()` methods handle the Toolbar widget navigation functionality.
+
+```java
+package com.auth0.samples.activities;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.auth0.samples.R;
+import com.auth0.samples.utils.ImageTask;
+import com.auth0.samples.utils.UserProfileManager;
+
+public class UserActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.user_activity);
+ Toolbar navToolbar = (Toolbar) findViewById(R.id.navToolbar);
+ setSupportActionBar(navToolbar);
+
+ TextView tvName = (TextView) findViewById(R.id.tvName);
+ TextView tvEmail = (TextView) findViewById(R.id.tvEmail);
+
+ tvName.setText(UserProfileManager.getUserInfo(this).getName());
+ tvEmail.setText(UserProfileManager.getUserInfo(this).getEmail());
+
+ new ImageTask((ImageView) findViewById(R.id.ivPicture))
+ .execute(UserProfileManager.getUserInfo(this).getPictureURL());
+
+ UserProfileManager.getUserInfo(this).getName();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu items for use in the action bar
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.user_action_menu, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_new:
+ startActivity(new Intent(UserActivity.this, FormActivity.class));
+ break;
+ case R.id.action_view:
+ startActivity(new Intent(UserActivity.this, TimeSheetActivity.class));
+ break;
+ default:
+ // If we got here, the user's action was not recognized.
+ // Invoke the superclass to handle it.
+ return super.onOptionsItemSelected(item);
+
+ }
+ return true;
+ }
+}
+```
+
+## 7. Form for New Timesheets
+
+Next create the `FormActivity` and layout to handle creating new timesheet entries.
+
+### Update the Manifest
+
+Open the app's `AndroidManifest.xml` and add the `FormActivity`:
+
+```xml
+
+```
+
+### Create the Form Activity Layouts
+
+Create the `form_activity.xml` layout with `EditText` for the project name and hours worked inputs, and a `DatePicker` for the day worked.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+And create the `form_actions_menu.xml` for the `FormActivity` Toolbar:
+
+```xml
+
+
+```
+
+### Create the Form Activity
+
+- The `@string/api_url` is set to `http://10.0.2.2:8080/timesheets` so the Android Emulator can connect to the Node.JS API running on `http://localhost:8080`.
+- The `onCreate()` method initializes the form and collects the input for the `postAPI()` method when the submit button is pressed.
+- The `postAPI()` method will send the user input retrieved from the form to the Node.JS API in JSON format.
+- The `clearForm()` method clears the input forms.
+- The `onCreateOptionsMenu()` and `onOptionsItemSelected()` methods handle the Toolbar widget navigation functionality.
+
+```java
+package com.auth0.samples.activities;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.DatePicker;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.auth0.android.Auth0;
+import com.auth0.android.authentication.AuthenticationAPIClient;
+import com.auth0.android.authentication.storage.CredentialsManager;
+import com.auth0.android.authentication.storage.CredentialsManagerException;
+import com.auth0.android.authentication.storage.SharedPreferencesStorage;
+import com.auth0.android.callback.BaseCallback;
+import com.auth0.android.result.Credentials;
+import com.auth0.samples.R;
+import com.squareup.okhttp.Callback;
+import com.squareup.okhttp.MediaType;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.RequestBody;
+import com.squareup.okhttp.Response;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Date;
+
+public class FormActivity extends AppCompatActivity {
+
+ private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
+
+ private String accessToken;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.form_activity);
+ Toolbar navToolbar = (Toolbar) findViewById(R.id.navToolbar);
+ setSupportActionBar(navToolbar);
+
+ Auth0 auth0 = new Auth0(getString(R.string.auth0_client_id), getString(R.string.auth0_domain));
+ auth0.setOIDCConformant(true);
+
+ AuthenticationAPIClient authAPIClient = new AuthenticationAPIClient(auth0);
+ SharedPreferencesStorage sharedPrefStorage = new SharedPreferencesStorage(this);
+
+ CredentialsManager credentialsManager = new CredentialsManager(authAPIClient, sharedPrefStorage);
+ credentialsManager.getCredentials(new BaseCallback() {
+ @Override
+ public void onSuccess(Credentials payload) {
+ accessToken = payload.getAccessToken();
+ }
+
+ @Override
+ public void onFailure(CredentialsManagerException error) {
+ Toast.makeText(FormActivity.this, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ Button submitTimeSheetButton = (Button) findViewById(R.id.submitTimeSheetButton);
+ final EditText editProjectName = (EditText) findViewById(R.id.editProjectName);
+ final EditText editHours = (EditText) findViewById(R.id.editHours);
+ final DatePicker datePicker = (DatePicker) findViewById(R.id.datePicker);
+
+ submitTimeSheetButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ int day = datePicker.getDayOfMonth();
+ int month = datePicker.getMonth();
+ int year = datePicker.getYear();
+
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(year, month, day);
+
+ postAPI(
+ editProjectName.getText().toString(),
+ calendar.getTime(),
+ editHours.getText().toString()
+ );
+ }
+ });
+ }
+
+ private void postAPI(String projectName, Date date, String hours) {
+
+ JSONObject postBody = new JSONObject();
+ try {
+ postBody.put("project", projectName);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ try {
+ postBody.put("date", date);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ try {
+ postBody.put("hours", hours);
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ String postStr = postBody.toString();
+
+ final Request.Builder reqBuilder = new Request.Builder()
+ .post(RequestBody.create(MEDIA_TYPE_JSON, postStr))
+ .url(getString(R.string.api_url))
+ .addHeader("Authorization", "Bearer " + accessToken);
+
+ OkHttpClient client = new OkHttpClient();
+ Request request = reqBuilder.build();
+
+ client.newCall(request).enqueue(new Callback() {
+ @Override
+ public void onFailure(Request request, IOException e) {
+ Log.e("API", "Error: ", e);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(FormActivity.this, "An error occurred", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ @Override
+ public void onResponse(final Response response) throws IOException {
+ final String resBody = response.body().string();
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (response.isSuccessful()) {
+ clearForm((ViewGroup) findViewById(R.id.mainForm));
+ Intent intent = new Intent(FormActivity.this, TimeSheetActivity.class);
+ FormActivity.this.startActivity(intent);
+ } else {
+ Toast.makeText(FormActivity.this, "Timesheet creation failed.", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+ });
+ }
+
+ private void clearForm(ViewGroup group) {
+ for (int i = 0, count = group.getChildCount(); i < count; ++i) {
+ View view = group.getChildAt(i);
+ if (view instanceof EditText) {
+ ((EditText)view).setText("");
+ }
+
+ if(view instanceof ViewGroup && (((ViewGroup)view).getChildCount() > 0))
+ clearForm((ViewGroup)view);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.form_action_menu, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_view:
+ startActivity(new Intent(FormActivity.this, TimeSheetActivity.class));
+ break;
+ case R.id.action_profile:
+ startActivity(new Intent(FormActivity.this, UserActivity.class));
+ break;
+ default:
+ return super.onOptionsItemSelected(item);
+
+ }
+ return true;
+ }
+}
+```
+
+## Test the App
+
+Before continuing, ensure you have [implemented the Node.JS API](/architecture-scenarios/application/mobile-api/api-implementation-nodejs).
+
+1. Start the API by navigating to the API's directory in your terminal and entering the `node server` command.
+2. Open the mobile app in Android Studio and press the __Run__ button.
+3. Select the Nexus 5X API 23 virtual device.
+4. Once the emulator has loaded the mobile app, you can login user then, create and view timesheet entries from the running Node.JS API.
+
+That's it! You are done!
diff --git a/articles/architecture-scenarios/mobile-api/part-1.md b/articles/architecture-scenarios/mobile-api/part-1.md
new file mode 100644
index 0000000000..dd7dcf520d
--- /dev/null
+++ b/articles/architecture-scenarios/mobile-api/part-1.md
@@ -0,0 +1,52 @@
+---
+description: Solutions Overview for the Mobile + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - mobile-apps
+ - api-auth
+ - authorization-code
+ - pkce
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - enable-mobile-auth
+ - build-an-app
+---
+
+# Mobile + API: Solutions Overview
+
+<%= include('../_includes/_api-overview-of-solution.md') %>
+
+<%= include('../_includes/_api-authentication-and-authorization.md') %>
+
+## Proof Key for Code Exchange (PKCE)
+
+OAuth 2 provides several grant types for different use cases. In this particular use case, we want to access the API from a mobile application, which will use the [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce) to do so.
+
+The [Authorization Code Flow](/flows/concepts/auth-code) has some security issues when implemented on native applications. For instance, a malicious attacker can intercept the `authorization_code` returned by Auth0 and exchange it for an [Access Token](/tokens/concepts/access-tokens) (and possibly a [Refresh Token](/tokens/concepts/refresh-tokens)).
+
+The Proof Key for Code Exchange (PKCE) (defined in [RFC 7636](https://tools.ietf.org/html/rfc7636)) is a technique used to mitigate this authorization code interception attack.
+
+With PKCE, the Application creates, for every authorization request, a cryptographically random key called `code_verifier` and its transformed value called `code_challenge`, which is sent to Auth0 to get the `authorization_code`. When the Application receives the `authorization_code`, it will send the code and the `code_verifier` to Auth0's token endpoint to exchange them for the requested tokens.
+
+
+
+1. The native app initiates the flow and redirects the user to Auth0 (specifically to the [/authorize endpoint](/api/authentication#authorization-code-grant-pkce-)), sending the `code_challenge` and `code_challenge_method` parameters.
+2. Auth0 redirects the user to the native app with an `authorization_code` in the query string.
+3. The native app sends the `authorization_code` and `code_verifier` together with the `redirect_uri` and the `client_id` to Auth0. This is done using the [/oauth/token endpoint](/api/authentication?http#authorization-code-pkce-).
+4. Auth0 validates this information and returns an Access Token (and optionally a Refresh Token).
+5. The native app can use the Access Token to call the API on behalf of the user.
+
+<%= include('../../_includes/_refresh_token_rotation_panel.md') %>
+
+## Authorization Extension
+
+The [Auth0 Authorization Extension](/extensions/authorization-extension) allows you to provide authorization support in your application, by assigning Roles, Groups and Permissions to Users.
+
+The Authorization Extension creates a [Rule](/rules) which will augment the [User profile](/rules/current#rule-syntax) during the authentication flow with the Roles, Groups and Permissions assigned to the user. You can then use this information to ensure that the Access Token issued to a user only contains scopes which are allowed according to the permissions defined in the Authorization Extension.
+
+<%= include('./_stepnav', {
+ prev: ["Introduction", "/architecture-scenarios/mobile-api"], next: ["2. Auth0 Configuration", "/architecture-scenarios/mobile-api/part-2"]
+}) %>
diff --git a/articles/architecture-scenarios/mobile-api/part-2.md b/articles/architecture-scenarios/mobile-api/part-2.md
new file mode 100644
index 0000000000..c9b8266765
--- /dev/null
+++ b/articles/architecture-scenarios/mobile-api/part-2.md
@@ -0,0 +1,129 @@
+---
+description: Auth0 Configuration for the Mobile + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - mobile-apps
+ - api-auth
+ - authorization-code
+ - pkce
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - enable-mobile-auth
+ - build-an-app
+---
+
+# Mobile + API: Auth0 Configuration
+
+In this section we will review all the configurations we need to apply at the [Auth0 Dashboard](${manage_url}).
+
+
+## Create the API
+
+Click on the [APIs menu option](${manage_url}/#/apis) on the left, and click the Create API button.
+
+You will be required to supply the following details for your API:
+
+- __Name__: a friendly name for the API. Does not affect any functionality.
+- __Identifier__: a unique identifier for the API. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all. This value cannot be modified afterwards.
+- __Signing Algorithm__: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting RS256 the token will be signed with the tenant's private key. To learn more about signing algorithms, see [Signing Algorithms](/tokens/concepts/signing-algorithms).
+
+
+
+Fill in the required information and click the __Create__ button.
+
+<%= include('../_includes/_api-signing-algorithms.md') %>
+
+<%= include('../_includes/_api-configure-scopes.md') %>
+
+## Create the Application
+
+There are four application types in Auth0: __Native App__ (used by mobile or desktop apps), __Single-Page Web App__, __Regular Web App__, and __Machine to Machine App__ (used by CLIs, Daemons, or services running on your backend). For this scenario we want to create a new Application for our mobile application, hence we will use Native as the application type.
+
+To create a new Application, navigate to the [dashboard](${manage_url}) and click on the [Applications](${manage_url}/#/applications}) menu option on the left. Click the __+ Create Application__ button.
+
+Set a name for your Application (we will use `Timesheets Mobile`) and select `Native App` as the type.
+
+Click __Create__.
+
+
+
+## Configure the Authorization Extension
+
+You will need to ensure that the Authorization Extension is installed for your tenant. You can refer to the [Authorization Extension documentation](/extensions/authorization-extension#how-to-install) for details on how to do this.
+
+### Define Permissions
+
+You will need to define Permissions which correlates with the scopes you have already defined. In the Authorization Extension, click the _Permissions_ tab, and then click on the **Create Permission** button. In the dialog, capture the details for each permission. Ensure that the name of the permission is exactly the same as the corresponding scope:
+
+
+
+Proceed to create the permissions for all the remaining scopes:
+
+
+
+### Define Roles
+
+Head over to the _Roles_ tab and create two Roles. Click the **Create Role** button and select the **Timesheets SPA** application. Give the Role a name and description of Employee, and select the `delete:timesheets`, `create:timesheets` and `read:timesheets` permissions. Click on **Save**.
+
+
+
+Next, follow the same process to create a **Manager** role, and ensure that you have selected all the permissions:
+
+
+
+### Assign Users to Roles
+
+You will need to assign all users to either the Manager or the User role. You can do this by going to the _Users_ tab in the Authorization Extension and selecting a user. On the user information screen, go to the _Roles_ tab. You can add a role to the user by clicking the **Add Role to User** button, and selecting the appropriate role for the user.
+
+
+
+### Configuring the Authorization Extension
+
+You will also need to ensure that the Rule for the Authorization Extension is published. You can do this by clicking on your user avatar in to top right of the Authorization Extension, and selecting the **Configuration** option:
+
+
+
+Ensure that you have enabled **Permissions** and then click the **Publish Rule** button:
+
+
+
+### Create a Rule to validate token scopes
+
+The final step in this process is to create a Rule which will validate that the scopes contained in an Access Token is valid based on the permissions assigned to the user. Any scopes which are not valid for a user should be removed from the Access Token.
+
+In your Auth0 Dashboard, go to the _Rules_ tab. You should see the Rule created by the Authorization Extension:
+
+
+
+Click on the **Create Rule** button and select the **Empty Rule** template. You can give the Rule a name, such as **Access Token Scopes**, and then specify the following code for the Rule:
+
+```js
+function (user, context, callback) {
+ if (context.clientName !== 'Timesheets SPA') {
+ return callback(null, user, context);
+ }
+
+ var permissions = user.permissions || [];
+ var requestedScopes = context.request.body.scope || context.request.query.scope;
+ var filteredScopes = requestedScopes.split(' ').filter( function(x) {
+ return x.indexOf(':') < 0;
+ });
+ Array.prototype.push.apply(filteredScopes, permissions);
+ context.accessToken.scope = filteredScopes.join(' ');
+
+ callback(null, user, context);
+}
+```
+
+The code above will ensure that all Access Tokens will only contain the properly-formatted scopes (e.g., `action:area` or `delete:timesheets`) which are valid according to a user's permissions. Once you are done you can click on the **Save** button.
+
+Rules execute in the order they are displayed on the Rules page, so ensure that the new rule you created is positioned below the rule for the Authorization Extension, so it executes after the Authorization Extension rule:
+
+
+
+<%= include('./_stepnav', {
+ prev: ["1. Solution Overview", "/architecture-scenarios/mobile-api/part-1"], next: ["3. API + Mobile Implementation", "/architecture-scenarios/mobile-api/part-3"]
+}) %>
diff --git a/articles/architecture-scenarios/mobile-api/part-3.md b/articles/architecture-scenarios/mobile-api/part-3.md
new file mode 100644
index 0000000000..153b761ec2
--- /dev/null
+++ b/articles/architecture-scenarios/mobile-api/part-3.md
@@ -0,0 +1,241 @@
+---
+description: API and Mobile Configuration for the Mobile + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - mobile-apps
+ - api-auth
+ - authorization-code
+ - pkce
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - enable-mobile-auth
+ - build-an-app
+---
+
+# Mobile + API: API and Mobile Configuration
+
+<%= include('../_includes/_api-implement.md') %>
+
+## Implement the Mobile App
+
+In this section we will see how we can implement a mobile application for our scenario.
+
+::: note
+[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#1-set-up-the-application)
+:::
+
+### Authorize the User
+
+To authorize the user we will implement the [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/guides/auth-code-pkce/call-api-auth-code-pkce). The mobile application should first send the user to the [authorization URL](/api/authentication#authorization-code-grant-pkce-) along with the `code_challenge` and the method used to generate it:
+
+```text
+https://${account.namespace}/authorize?
+ audience=API_AUDIENCE&
+ scope=SCOPE&
+ response_type=code&
+ client_id=YOUR_CLIENT_ID&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256&
+ redirect_uri=https://YOUR_APP/callback
+```
+
+The `GET` request to the authorization URL should include the following values:
+
+Parameter | Description
+----------|------------
+__client_id__ | The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Auth0 Dashboard](${manage_url}/#/applications).
+__audience__ | The value of your API Identifier. You can retrieve it from the Settings of your API at the [Auth0 Dashboard](${manage_url}/#/apis).
+__scope__ | The [scopes](/scopes) which determine the claims to be returned in the ID Token and Access Token. For example, a scope of `openid` will return an ID Token in the response. In our example mobile app, we use the following scopes: `create:timesheets read:timesheets openid profile email offline_access`. These scopes allow the mobile app to call the API, obtain a Refresh Token, and return the user's `name`, `picture`, and `email` claims in the ID Token.
+__response_type__ | Indicates the Authentication Flow to use. For a mobile application using PKCE, this should be set to `code`.
+__code_challenge__ | The generated code challenge from the code verifier. You can find instructions on generating a code challenge [here](/flows/guides/auth-code-pkce/call-api-auth-code-pkce#authorize-the-user#create-a-code-verifier).
+__code_challenge_method__ | Method used to generate the challenge. Auth0 supports only `S256`.
+__redirect_uri__ | The URL which Auth0 will redirect the browser to after authorization has been granted by the user. The Authorization Code will be available in the code URL parameter. This URL must be specified as a valid callback URL under your [Application's Settings](${manage_url}/#/applications).
+
+::: note
+[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#2-authorize-the-user)
+:::
+
+### Get the Credentials
+
+After a successful request to the authorization URL, you should receive the following response:
+
+```text
+HTTP/1.1 302 Found
+Location: https://${account.namespace}/callback?code=AUTHORIZATION_CODE
+```
+
+Next you can exchange the `authorization_code` from the response for an Access Token that can be used to call your API. Perform a `POST` request to the [Token URL](/api/authentication#authorization-code-pkce-) including the following data:
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData": {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "code_verified",
+ "value": "YOUR_GENERATED_CODE_VERIFIER"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "https://${account.callback}"
+ }
+ ]
+ }
+}
+```
+
+Parameter | Description
+----------|------------
+__grant_type__ | This must be set to `authorization_code`.
+__client_id__ | The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Auth0 Dashboard](${manage_url}/#/applications).
+__code_verifier__ | Cryptographically random key that was used to generate the `code_challenge` passed to [authorization URL](/api/authentication#authorization-code-grant-pkce-) (`/authorize`).
+__code__ | The `authorization_code` received from the previous authorize call.
+__redirect_uri__ | The URL must match the `redirect_uri` passed in the previous section to `/authorize`.
+
+The response from the Token URL will contain:
+
+```json
+{
+ "access_token": "eyJz93a...k4laUWw",
+ "refresh_token": "GEbRxBN...edjnXbL",
+ "id_token": "eyJ0XAi...4faeEoQ",
+ "token_type": "Bearer",
+ "expires_in":86400
+}
+```
+
+- __access_token__: An Access Token for the API, specified by the `audience`.
+- __refresh_token__: A [Refresh Token](/tokens/concepts/refresh-tokens) will only be present if you included the `offline_access` scope AND enabled __Allow Offline Access__ for your API in the Dashboard.
+- __id_token__: An ID Token JWT containing user profile information.
+- __token_type__: A string containing the type of token, this will always be a Bearer token.
+- __expires_in__: The amount of seconds until the Access Token expires.
+
+You will need to store the above credentials in local storage for use in calling your API and retrieving the user profile.
+
+::: note
+[See the implementation in Android](/architecture-scenarios/application/mobile-api/mobile-implementation-android#store-credentials).
+:::
+
+### Get the User Profile
+
+To retrieve the [User Profile](/api/authentication?http#user-profile), your mobile application can decode the [ID Token](/tokens/concepts/id-tokens) using one of the [JWT libraries](https://jwt.io/#libraries-io). This is done by [verifying the signature](/tokens/guides/validate-id-token#verify-the-signature) and [verifying the claims](/tokens/guides/validate-id-token#verify-the-claims) of the token. After validating the ID Token, you can access its payload containing the user information:
+
+```json
+{
+ "email_verified": false,
+ "email": "test.account@userinfo.com",
+ "clientID": "q2hnj2iu...",
+ "updated_at": "2016-12-05T15:15:40.545Z",
+ "name": "test.account@userinfo.com",
+ "picture": "https://s.gravatar.com/avatar/dummy.png",
+ "user_id": "auth0|58454...",
+ "nickname": "test.account",
+ "created_at": "2016-12-05T11:16:59.640Z",
+ "sub": "auth0|58454..."
+}
+```
+
+::: note
+[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#3-get-the-user-profile)
+:::
+
+### Display UI Elements Conditionally Based on Scope
+
+Based on the `scope` of the user, you may want to show or hide certain UI elements. To determine the scope issued to a user, you will need to inspect the `scope` which was granted when the user was authenticated. This will be a string containing all the scopes, so you therefore need to inspect this string to see whether it contains the required `scope` and based on that make a decision whether to display a particular UI element.
+
+::: note
+[See the implementation in Android](/architecture-scenarios/application/mobile-api/mobile-implementation-android#4-display-ui-elements-conditionally-based-on-scope)
+:::
+
+### Call the API
+
+To access secured resources from your API, the authenticated user's Access Token needs to be included in requests that are sent to it. This is accomplished by sending the Access Token in an `Authorization` header using the `Bearer` scheme.
+
+::: note
+[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#5-call-the-api)
+:::
+
+### Renew the Token
+
+::: warning
+Refresh Tokens must be stored securely by an application since they do not expire and allow a user to remain authenticated essentially forever. If Refresh Tokens are compromised or you no longer need them, you can revoke the Refresh Tokens using the [Authentication API](/api/authentication#revoke-refresh-token).
+:::
+
+To refresh your Access Token, perform a `POST` request to the `/oauth/token` endpoint using the Refresh Token from your authorization result.
+
+A [Refresh Token](/tokens/concepts/refresh-tokens) will only be present if you included the `offline_access` scope in the previous authorization request and enabled __Allow Offline Access__ for your API in the Dashboard.
+
+Your request should include:
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "httpVersion": "HTTP/1.1",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "refresh_token"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "refresh_token",
+ "value": "YOUR_REFRESH_TOKEN"
+ }
+ ]
+ }
+}
+```
+
+Parameter | Description
+----------|------------
+__grant_type__ | This must be set to `refresh_token`.
+__client_id__ | The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Auth0 Dashboard](${manage_url}/#/applications).
+__refresh_token__ | the Refresh Token to use, from the previous authentication result.
+
+The response will include the new Access Token:
+
+```json
+{
+ "access_token": "eyJz93a...k4laUWw",
+ "refresh_token": "GEbRxBN...edjnXbL",
+ "id_token": "eyJ0XAi...4faeEoQ",
+ "token_type": "Bearer",
+ "expires_in":86400
+}
+```
+
+::: note
+[See the implementation in Android.](/architecture-scenarios/application/mobile-api/mobile-implementation-android#store-the-credentials)
+:::
+
+<%= include('./_stepnav', {
+ prev: ["2. Auth0 Configuration", "/architecture-scenarios/mobile-api/part-2"], next: ["Conclusion", "/architecture-scenarios/mobile-api/part-4"]
+}) %>
diff --git a/articles/architecture-scenarios/mobile-api/part-4.md b/articles/architecture-scenarios/mobile-api/part-4.md
new file mode 100644
index 0000000000..4807bfa6a7
--- /dev/null
+++ b/articles/architecture-scenarios/mobile-api/part-4.md
@@ -0,0 +1,31 @@
+---
+description: Conclusion for the Mobile + API architecture scenario
+topics:
+ - architecture
+ - mobile-apps
+ - api-auth
+ - authorization-code
+ - pkce
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - enable-mobile-auth
+ - build-an-app
+---
+
+# Mobile + API: Conclusion
+
+In this document we covered a simple scenario: an API, used by a mobile application to allow employees to capture their timesheets.
+
+We learned about the Authorization Code Grant with PKCE, what an Access Token is, how to configure an API in Auth0, how to configure a mobile application to communicate securely with this API, how to define and secure our API endpoints, how to use the provided libraries to validate the Access Token and how to retrieve a new one from Auth0.
+
+We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
+
+We used Node.js for the API implementation and Android for the mobile application. Hopefully though after going through this document you are able to build this using the technologies you prefer.
+
+Don't forget to check back for new business cases and more complex architecture scenarios!
+
+<%= include('./_stepnav', {
+ prev: ["3. API + Mobile Implementation", "/architecture-scenarios/mobile-api/part-3"]
+}) %>
diff --git a/articles/architecture-scenarios/application/server-api/_stepnav.html b/articles/architecture-scenarios/server-api/_stepnav.html
similarity index 100%
rename from articles/architecture-scenarios/application/server-api/_stepnav.html
rename to articles/architecture-scenarios/server-api/_stepnav.html
diff --git a/articles/architecture-scenarios/server-api/api-implementation-nodejs.md b/articles/architecture-scenarios/server-api/api-implementation-nodejs.md
new file mode 100644
index 0000000000..d52ffd389a
--- /dev/null
+++ b/articles/architecture-scenarios/server-api/api-implementation-nodejs.md
@@ -0,0 +1,209 @@
+---
+title: "Server Client + API: Node.js Implementation for the API"
+description: The Node.js implementation of the API for the Server Client + API architecture scenario
+topics:
+ - architecture
+ - server-apps
+ - api-auth
+ - authorization-code
+ - client-credentials
+ - nodejs
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+# Server Client + API: Node.js Implementation for the API
+
+::: panel Server + API Architecture Scenario
+This document is part of the [Server + API Architecture Scenario](/architecture-scenarios/application/server-api) and it explains how to implement the API in Node.js. Please refer to the scenario for information on the implemented solution.
+:::
+
+Full source code for the Node.js API implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).
+
+## 1. Define the API endpoint
+
+We will use the [Express web application framework](http://expressjs.com/) to build our Node.js API.
+
+### Create a package.json File
+
+Create a folder for your API, navigate into it and run `npm init`. This will setup your `package.json` file.
+
+You can leave the default settings or change them as you see fit.
+
+Our sample’s `package.json` looks like the following:
+
+```json
+{
+ "name": "timesheets-api",
+ "version": "1.0.0",
+ "description": "API used to add timesheet entries for employees and contractors",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
+ },
+ "author": "Auth0",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
+ },
+ "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
+}
+```
+
+### Install the Dependencies
+
+Next, we need to set our dependencies. We will use the following modules:
+
+- **express**: This module adds the [Express web application framework](https://expressjs.com/).
+
+- **jwks-rsa**: This library retrieves RSA signing keys from a [**JWKS** (JSON Web Key Set)](/tokens/concepts/jwks) endpoint. Using `expressJwtSecret` we can generate a secret provider that will provide the right signing key to `express-jwt` based on the `kid` in the JWT header. For more information refer to the [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
+
+- **express-jwt**: This module lets you authenticate HTTP requests using JWT tokens in your Node.js applications. It provides several functions that make working with JWTs easier. For more information refer to the [express-jwt GitHub repository](https://github.com/auth0/express-jwt).
+
+- **body-parser**: This is a Node.js body parsing middleware. It extracts the entire body portion of an incoming request stream and exposes it on `req.body` as something easier to interface with.For more information and several alternatives refer to the body-parser GitHub repository.
+
+To install these dependencies run the following:
+
+```bash
+npm install express express-jwt jwks-rsa body-parser --save
+```
+
+### Implement the Endpoint
+
+Navigate to your API directory and create a `server.js` file. Your code needs to:
+- Set the dependencies.
+- Enable the request body parsing middleware.
+- Implement the endpoint.
+- Launch the API server.
+
+This is our sample implementation:
+
+```js
+// set dependencies
+const express = require('express');
+const app = express();
+const jwt = require('express-jwt');
+const jwksRsa = require('jwks-rsa');
+const bodyParser = require('body-parser');
+
+// enable the use of request body parsing middleware
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({
+ extended: true
+}));
+
+// create timesheets upload API endpoint
+app.post('/timesheets/upload', function(req, res){
+ res.status(201).send({message: "This is the POST /timesheets/upload endpoint"});
+})
+
+// launch the API Server at localhost:8080
+app.listen(8080);
+```
+
+Launch your API server using `node server` and make an HTTP POST request to `localhost:8080/timesheets/upload`. You should see a JSON response with a message `This is the POST /timesheets/upload endpoint`.
+
+So now we have our endpoint but anyone can call it. Continue to the next paragraph to see how we can fix this.
+
+## 2. Secure the API endpoint
+
+In order to validate our token we will use the `jwt` function, provided by the [express-jwt middleware](https://github.com/auth0/express-jwt#usage), and the `jwks-rsa` package to retrieve the public key from Auth0. The libraries do the following:
+
+1. `express-jwt` will decode the token and pass the request, the header and the payload to `jwksRsa.expressJwtSecret`.
+
+1. `jwks-rsa` will then download all signing keys from the JWKS endpoint and see if a one of the signing keys matches the `kid` in the header of the JWT. If none of the signing keys match the incoming `kid`, an error will be thrown. If we have a match, we will pass the right signing key to `express-jwt`.
+
+1. `express-jwt` will the continue its own logic to validate the signature of the token, the expiration, `audience` and the `issuer`.
+
+The steps we will follow in our code are:
+- Create the middleware function to validate the Access Token.
+- Enable the use of the middleware in our routes.
+
+This is also a good time for you to implement the logic to save the timesheet entries to a local database, or whatever other storage mechanism you may prefer. This is our sample implementation (some code is omitted for brevity):
+
+```js
+// set dependencies - code omitted
+
+// enable the use of request body parsing middleware - code omitted
+
+// Create middleware for checking the JWT
+const checkJwt = jwt({
+ // Dynamically provide a signing key based on the kid in the header and the signing keys provided by the JWKS endpoint.
+ secret: jwksRsa.expressJwtSecret({
+ cache: true,
+ rateLimit: true,
+ jwksRequestsPerMinute: 5,
+ jwksUri: `https://${account.namespace}/.well-known/jwks.json`
+ }),
+
+ // Validate the audience and the issuer.
+ audience: process.env.AUTH0_AUDIENCE,
+ issuer: `https://${account.namespace}/`,
+ algorithms: ['RS256']
+});
+
+// create timesheets API endpoint
+app.post('/timesheets/upload', checkJwt, function(req, res){
+ var timesheet = req.body;
+
+ // Save the timesheet entry to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+})
+
+// launch the API Server at localhost:8080 - code omitted
+```
+
+If we launch our server now and do an HTTP POST to `localhost:8080/timesheets/upload` we should get the error message `Missing or invalid token` (which is perfectly fine since we didn’t send an Access Token in our request).
+
+In order to test the working scenario as well we need to:
+- Get an Access Token. For details on how to do so refer to: [Get an Access Token](/architecture-scenarios/application/server-api#get-an-access-token).
+- Invoke the API while adding an `Authorization` header to our request with the value `Bearer ACCESS_TOKEN` (where *ACCESS_TOKEN* is the value of the token we retrieved in the first step).
+
+## 3. Check the Client permissions
+
+In this step we will add to our implementation the ability to check if the client has permissions (or `scope`) to use our endpoint in order to upload a timesheet. In particular we want to ensure that the token has the correct scope, which is `batch:upload`.
+
+In order to do this we will make use of the `express-jwt-authz` Node.js package, so go ahead and add that to your project:
+
+```bash
+npm install express-jwt-authz --save
+```
+
+Now it is as simple as adding a call to `jwtAuthz(...)` to your middleware to ensure that the JWT contain a particular scope in order to execute a particular endpoint. This is our sample implementation (some code is omitted for brevity):
+
+```js
+// set dependencies - some code omitted
+const jwtAuthz = require('express-jwt-authz');
+
+// Create middleware for checking the JWT
+
+// Enable the use of request body parsing middleware
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({
+ extended: true
+}));
+
+// Batch upload endpoint
+app.post('/timesheets/upload', checkJwt, jwtAuthz(['batch:upload']), function(req, res){
+ var timesheet = req.body;
+
+ // Save the timesheet entry to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+});
+
+// launch the API Server at localhost:8080 - code omitted
+```
+
+If we invoke our API with a token that does not include this scope we should get the error message Forbidden with the HTTP status code `403`. You can test this by removing this scope from your API.
+
+That's it! You are done!
diff --git a/articles/architecture-scenarios/server-api/cron-implementation-python.md b/articles/architecture-scenarios/server-api/cron-implementation-python.md
new file mode 100644
index 0000000000..4b63fa532b
--- /dev/null
+++ b/articles/architecture-scenarios/server-api/cron-implementation-python.md
@@ -0,0 +1,111 @@
+---
+title: "Server Client + API: Python Implementation for the Cron Job"
+description: The Python implementation of the server cron job for the Server Client + API architecture scenario
+topics:
+ - architecture
+ - server-apps
+ - api-auth
+ - authorization-code
+ - client-credentials
+ - python
+ - cron-job
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Server Client + API: Python Implementation for the Cron Job
+
+::: panel Server + API Architecture Scenario
+This document is part of the [Server + API Architecture Scenario](/architecture-scenarios/application/server-api) and it explains how to implement the server process in Python. Please refer to the [Server + API Architecture Scenario](/architecture-scenarios/application/server-api) document for information on the implemented solution.
+:::
+
+Full source code for the Python implementation of the server process can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-cron/python).
+
+## Get an Access Token
+
+In order to make the HTTP request to the Auth0 `/oauth/token` API endpoint we will use the libraries `json`, `urllib` and `urllib2`.
+
+This is our sample implementation:
+
+```python
+def main():
+ import json, urllib, urllib2, httplib
+
+ # Configuration Values
+ domain = "${account.namespace}" # Your Auth0 Domain
+ api_identifier = "API_IDENTIFIER" # API Identifier of your API
+ client_id = "${account.clientId}" # Client ID of your Machine to Machine Application
+ client_secret = "YOUR_CLIENT_SECRET" # Client Secret of your Machine to Machine Application
+ api_url = "http://localhost:8080/timesheets/upload"
+ grant_type = "client_credentials" # OAuth 2.0 flow to use
+
+ # Get an Access Token from Auth0
+ base_url = "https://{domain}".format(domain=domain)
+ data = urllib.urlencode({'client_id': client_id,
+ 'client_secret': client_secret,
+ 'audience': api_identifier,
+ 'grant_type': grant_type})
+ req = urllib2.Request(base_url + "/oauth/token", data, headers={"Accept": "application/x-www-form-urlencoded"})
+ response = urllib2.urlopen(req)
+ resp_body = response.read()
+ oauth = json.loads(resp_body)
+ access_token = oauth['access_token']
+
+# Standard boilerplate to call the main() function.
+if __name__ == '__main__':
+ main()
+```
+
+To test this modify your code to print the `access_token` variable and run the process using `python cron.py`.
+
+## Invoke the API
+
+The steps we follow in our implementation are:
+- Build a JSON object containing timesheet data and assign it to a `timesheet` variable.
+- Add the API URL and the `timesheet` variable contents to the request body using `urllib2.Request`.
+- Add the `Authorization` header to the request.
+- Set the `Content-Type` header to `application/json`.
+- Invoke the API using `urllib2.urlopen` and add some error handling.
+Retrieve the response using `json.loads` and print it in the console.
+
+This is our sample implementation (some code is omitted for brevity):
+
+```python
+def main():
+ # import libraries - code omitted
+
+ # Configuration Values - code omitted
+
+ # Get an Access Token from Auth0 - code omitted
+
+ #Post new timesheet to API
+ timesheet = {'user_id': '007',
+ 'date': '2017-05-10T17:40:20.095Z',
+ 'project': 'StoreZero',
+ 'hours': 5}
+ req = urllib2.Request(api_url, data = json.dumps(timesheet))
+ req.add_header('Authorization', 'Bearer ' + access_token)
+ req.add_header('Content-Type', 'application/json')
+
+ try:
+ response = urllib2.urlopen(req)
+ res = json.loads(response.read())
+ print 'Created timesheet ' + str(res['id']) + ' for employee ' + str(res['user_id'])
+ except urllib2.HTTPError, e:
+ print 'HTTPError = ' + str(e.code) + ' ' + str(e.reason)
+ except urllib2.URLError, e:
+ print 'URLError = ' + str(e.reason)
+ except httplib.HTTPException, e:
+ print 'HTTPException'
+ except Exception, e:
+ print 'Generic Exception' + str(e)
+
+# Standard boilerplate to call the main() function - code omitted
+```
+
+To test this make sure your API is running and run the process using `python cron.py`.
+
+That's it! You are done!
diff --git a/articles/architecture-scenarios/server-api/index.md b/articles/architecture-scenarios/server-api/index.md
new file mode 100644
index 0000000000..85d94e5a96
--- /dev/null
+++ b/articles/architecture-scenarios/server-api/index.md
@@ -0,0 +1,50 @@
+---
+order: 02
+title: Server Application + API
+image: /media/articles/architecture-scenarios/server-api.png
+extract: Server to server communication where a server “Application” needs to make secure calls to an API (“Resource Server”), but on behalf of the application vs. a user.
+description: Explains the architecture scenario with server to server communication with secure calls to an API (“Resource Server”), but on behalf of the application vs. a user.
+toc: true
+topics:
+ - architecture
+ - server-apps
+ - api-auth
+ - authorization-code
+ - client-credentials
+contentType:
+ - tutorial
+ - index
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Server + API
+
+In this scenario we will build a Timesheet API for a fictitious company named ExampleCo. The API will allow to add timesheet entries for an employee or a contractor.
+
+We will also be building a cron job which will process timesheet entries from an external system to the centralized timesheet database using the API.
+
+::: panel TL;DR
+* Auth0 provides API Authentication and Authorization as a means to secure access to API endpoints (see [API Authentication and Authorization](/architecture-scenarios/server-api/part-1#api-authentication-and-authorization))
+* For authorizing a Machine to Machine Application (a CLI, service or daemon where no user interaction is involved) Auth0 supports the Client Credentials grant (see [Client Credentials Grant](/architecture-scenarios/server-api/part-1#client-credentials-grant))
+* Both the Machine to Machine Application and the API must be configured in the Auth0 Dashboard (see [Auth0 Configuration](/architecture-scenarios/server-api/part-2))
+* The API will be secured by ensuring that a valid Access Token (which is implemented as a JSON Web Token) is passed in the HTTP Authorization header when calls are made to the API (see [Implement the API](/architecture-scenarios/server-api/part-3))
+* Upon successful authorization an Access Token is issued to the Machine to Machine Application (see [Get an Access Token](/architecture-scenarios/server-api/part-3#get-an-access-token))
+* The Machine to Machine Application can in turn use this Access Token to pass along as an HTTP Authorization header to authenticate calls to API endpoints (see [Invoke the API](/architecture-scenarios/server-api/part-3#invoke-the-api))
+:::
+
+## The Premise
+
+ExampleCo is a consulting startup company. Currently they have approximately 100 employees and they also outsource several activities to external contractors. All employees and external contractors are required to fill in their timesheets every week. For this purpose, they built a timesheets application, a scenario we covered in [Single Sign-On for Regular Web Apps](/architecture-scenarios/web-app-sso). The internal employees use this web app to fill in their timesheets but some of the external contractors already use another tool to track their timesheets. Hence a solution to avoid the double work is required. It was decided to build a cron job which will read the timesheet entries from this external system, and automatically upload those to ExampleCo's backend using an API.
+
+### Goals & Requirements
+
+ExampleCo wants to build a flexible solution. At the moment only an automated process needs to push timesheet entries but in the future the company plans on launching more applications, like a mobile app to accommodate their sales teams. Hence the company has decided to develop a single Timesheets API which will be used to log time not only by this server process, but by all future applications as well. They want to put in place a security architecture that is flexible enough to accommodate this. ExampleCo wants to ensure that a large part of the code and business logic for the application can be shared across the different applications.
+
+It is required that only authorized users and applications are allowed access to the Timesheets API.
+
+<%= include('./_stepnav', {
+ next: ["1. Solution Overview", "/architecture-scenarios/server-api/part-1"]
+}) %>
diff --git a/articles/architecture-scenarios/server-api/part-1.md b/articles/architecture-scenarios/server-api/part-1.md
new file mode 100644
index 0000000000..13890c3dfb
--- /dev/null
+++ b/articles/architecture-scenarios/server-api/part-1.md
@@ -0,0 +1,39 @@
+---
+description: Solutions Overview for the Server + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - server-apps
+ - api-auth
+ - authorization-code
+ - client-credentials
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Server + API: Solution Overview
+
+<%= include('../_includes/_api-overview-of-solution.md') %>
+
+<%= include('../_includes/_api-authentication-and-authorization.md') %>
+
+## Client Credentials Grant
+
+OAuth 2 provides several *grant types* for different use cases. In this particular use case where a cron job will be uploading timesheets via an API, there is no interactive user (or resource owner) who grants permission to the cron job to access the API.
+
+The cron job is also not making the API calls on behalf of any user. Instead there is a machine to machine authorization and the application (the cron job) makes calls to the Resource Server (the API) on its own behalf.
+
+For situations like this where there is no user interaction involved, the Client Credentials Grant is ideal. With Client Credentials Grant (defined in [RFC 6749, section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)) an Application can directly request an Access Token from the Authorization Server by using its Client Credentials (a Client Id and a Client Secret). Instead of identifying a Resource Owner, this token will represent the Application itself.
+
+
+
+1. The Application authenticates with the Authorization Server using its Client ID and Client Secret.
+1. The Authorization Server validates this information and returns an Access Token.
+1. The Application can use the Access Token to call the Resource Server on behalf of itself.
+
+<%= include('./_stepnav', {
+ prev: ["Introduction", "/architecture-scenarios/server-api"], next: ["2. Auth0 Configuration", "/architecture-scenarios/server-api/part-2"]
+}) %>
diff --git a/articles/architecture-scenarios/server-api/part-2.md b/articles/architecture-scenarios/server-api/part-2.md
new file mode 100644
index 0000000000..431f5d2c86
--- /dev/null
+++ b/articles/architecture-scenarios/server-api/part-2.md
@@ -0,0 +1,100 @@
+---
+description: Auth0 Configuration for the Server + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - server-apps
+ - api-auth
+ - authorization-code
+ - client-credentials
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Server + API: Auth0 Configuration
+
+In this section, we will review all the configurations we need to apply using the [Auth0 Dashboard](${manage_url}).
+
+## Configure the API
+
+Click on the [APIs menu option](${manage_url}/#/apis) on the left, and click the **Create API** button.
+
+You will be required to supply the following details for your API:
+
+- **Name**: Friendly name for the API. Does not affect any functionality.
+- **Identifier**: Unique identifier for the API. We recommend using a URL, but this doesn't have to be a publicly available URL; Auth0 will not call your API at all. This value cannot be modified afterwards.
+- **Signing Algorithm**: Algorithm to sign the tokens with. Available values are `HS256` and `RS256`. When selecting RS256, the token will be signed with the tenant's private key. To learn more about signing algorithms, see [Signing Algorithms](/tokens/concepts/signing-algorithms).
+
+
+
+Fill in the required information, and click the **Create** button.
+
+### Signing Algorithms
+
+When you create an API, you must select the algorithm with which your tokens will be signed. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
+
+::: note
+The signature is part of a JWT. If you are unfamiliar with JWT structure, please see [JSON Web Token Structure](/tokens/references/jwt-structure).
+:::
+
+To create the signature, you must take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. That algorithm, which is part of the JWT header, is the one you select for your API: `HS256` or `RS256`.
+
+- **RS256** is an [asymmetric algorithm](https://en.wikipedia.org/wiki/Public-key_cryptography) which means that there are two keys: one public and one private (secret). Auth0 has the secret key, which is used to generate the signature, and the consumer of the JWT has the public key, which is used to validate the signature.
+
+- **HS256** is a [symmetric algorithm](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which means that there is only one secret key, shared between the two parties. The same key is used both to generate the signature and to validate it. Special care should be taken in order for the key to remain confidential.
+
+The most secure practice, and our recommendation, is to use **RS256**. Some of the reasons are:
+
+- With RS256, you are sure that only the holder of the private key (Auth0) can sign tokens, while anyone can check if the token is valid using the public key.
+- Under HS256, if the private key is compromised you would have to re-deploy the API with the new secret. With RS256, you can request a token that is valid for multiple audiences.
+- With RS256, you can implement key rotation without having to re-deploy the API with the new secret.
+
+## Configure the Scopes
+
+Once the application has been created, you will need to configure the Scopes that applications can request during authorization.
+
+In the settings for your API, go to the *Scopes* tab. In this section, you can add all four of the scopes discussed before: `batch:upload`, `read:timesheets`, `create:timesheets`, `delete:timesheets`, and `approve:timesheets`. Also add an additional scope: `batch:upload`.
+
+::: note
+ For the purpose of this document, we will only be concerned with the `batch:upload` scope because that is all that is required by the cron job. However, for the sake of completeness, we are adding the necessary scopes which will be required by future applications.
+:::
+
+
+
+## Create the Application
+
+When creating an API in the Auth0 Dashboard, a test application for the API will automatically be generated. In the Auth0 Dashboard, navigate to the [Application Section](${manage_url}/#/applications), and you will see the test application for the Timesheets API.
+
+
+
+Go to the settings for the application by clicking on the gear icon, and rename the application to `Timesheets import Job`.
+
+For the cron job, you will need a Machine-to-Machine Application. The test application that was generated when the API was created was automatically configured as a Machine-to-Machine Application:
+
+
+
+## Configure Application's access to the API
+
+Finally, you must allow the application access to the Timesheets API. Go back to the configuration of the API, and select the *Machine to Machine Application* tab.
+
+You will see the **Timesheets Import Job** application listed, and it should have access to API as can be seen from the switch to the right of the application name which indicates a value of `Authorized`. If it does not indicate that the application is authorized, simply toggle the value of the switch from `Unauthorized` to `Authorized`.
+
+
+
+You will also need to specify which scopes will be included in Access Tokens that are issued to the application when the application authorizes with Auth0.
+
+Expand the settings for the application by clicking on the down arrow to the far right, and you will see the list of available scopes. The cron job will only require the `batch:upload` scope as it will simply create new timesheets based on the timesheet entries in the external system.
+
+Once you have selected the `batch:upload` scope, save the settings by clicking the **Update** button.
+
+
+
+Now that we have designed our solution and discussed the configurations needed on Auth0's side, we can proceed with the implementation. That's what the next paragraph is all about, so keep reading!
+
+
+<%= include('./_stepnav', {
+ prev: ["1. Solution Overview ", "/architecture-scenarios/server-api/part-1"], next: ["3. Application Implementation", "/architecture-scenarios/server-api/part-3"]
+}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/server-api/part-3.md b/articles/architecture-scenarios/server-api/part-3.md
new file mode 100644
index 0000000000..86e00db211
--- /dev/null
+++ b/articles/architecture-scenarios/server-api/part-3.md
@@ -0,0 +1,148 @@
+---
+description: Application Implementation for the Server + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - server-apps
+ - api-auth
+ - authorization-code
+ - client-credentials
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Server + API: Application Implementation
+
+In this section of the tutorial, we will take an in-depth look into our API and its associated Machine to Machine Application.
+
+::: note
+For simplicity, we will keep our implementation solely focused on authentication and authorization. As you will see in the samples, the input timesheet entry will be hard-coded, and the API will not persist the timesheet entry. Instead, it will simply echo back some of the info.
+:::
+
+## Define the API endpoints
+
+First, we need to define the endpoints of our API.
+
+::: panel What is an API endpoint?
+An **API endpoint** is a unique URL that represents an object. To interact with this object, you need to point your application to its URL. For example, if you had an API that could return either orders or customers, you might configure two endpoints: `/orders` and `/customers`. Your application would interact with these endpoints using different HTTP methods; for example, `POST /orders` could create a new order or `GET /orders` could retrieve the dataset of one or more orders.
+:::
+
+We will configure one single endpoint that will be used to create timesheet entries. The endpoint will be `/timesheets/upload` and the HTTP method will be `POST`.
+
+As input, the API will expect a JSON object containing the timesheet information. We will use the following JSON:
+
+```json
+{
+ 'user_id': '007',
+ 'date': '2017-05-10T17:40:20.095Z',
+ 'project': 'StoreZero',
+ 'hours': 5
+}
+```
+
+The API will print the JSON, so we can verify the contents and echo back a message like the following: `Created timesheet 14 for employee 007`.
+
+::: note
+See the implementation in [Node.js](/architecture-scenarios/application/server-api/api-implementation-nodejs#1-define-the-api-endpoint).
+:::
+
+### Secure the API endpoints
+
+::: panel-warning Configure the API
+To secure your endpoints, you need to have your API configured in the Auth0 Dashboard. To learn how, see the [Configure the API](#configure-the-api) paragraph of this document.
+:::
+
+The first step towards securing our API endpoint is to get an Access Token as part of the Header and validate it. If it's not valid, then we should return an HTTP Status 401 (Unauthorized) to the calling process.
+
+::: note
+See the implementation in [Node.js](/architecture-scenarios/application/server-api/api-implementation-nodejs#2-secure-the-api-endpoint).
+:::
+
+#### Get an Access Token
+
+To get an Access Token without using our application sample implementation, perform a `POST` operation to the `https://${account.namespace}/oauth/token` endpoint with a payload in the following format:
+
+```json
+{
+ audience: "YOUR_API_IDENTIFIER",
+ grant_type: "client_credentials",
+ client_id: "${account.client_id}",
+ client_secret: "${account.client_secret}"
+}
+```
+
+::: note
+To learn more, see [API Authorization: Asking for Access Tokens for a Client Credentials Grant](/api-auth/config/asking-for-access-tokens).
+:::
+
+## Check the application permissions
+
+Now we have secured our API's endpoint with an Access Token, but we still haven't ensured that the process calling the API has the rights to post a new timesheet entry.
+
+As discussed earlier in this doc, each Access Token may include a list of the permissions that have been granted to the client. These permissions are defined using the `scope` request parameter. To learn how to configure this, see the [Configure the Scopes](#configure-the-scopes) paragraph.
+
+For our endpoint, we will require the scope `batch:upload`.
+
+::: note
+See the implementation in [Node.js](/architecture-scenarios/application/server-api/api-implementation-nodejs#3-check-the-client-permissions).
+:::
+
+### Implement the Machine to Machine Application
+
+In this section, we will see how we can implement a Machine-to-Machine Application for our scenario.
+
+::: note
+For simplicity, we will keep our implementation solely focused on authentication and authorization, and configure our application to send a single hard-coded timesheet entry to the API. Also, we will print in the console, which is something we wouldn't do with a server-running process.
+:::
+
+### Get an Access Token
+
+We will start by invoking the Auth0 `/oauth/token` API endpoint to get an Access Token.
+
+To do so, we will need the following configuration values:
+
+- **Domain**: Auth0 Domain, which you can retrieve from the *Settings* of your application in the [Auth0 Dashboard](${manage_url}/#/applications). This value will be a part of the API URL: `https://${account.namespace}/oauth/token`.
+
+- **Audience**: API Identifier, which you can retrieve from the *Settings* of your API in the [Auth0 Dashboard](${manage_url}/#/apis).
+
+- **Client ID**: Auth0 Application's Client ID, which you can retrieve from the *Settings* of your application in the [Auth0 Dashboard](${manage_url}/#/applications).
+
+- **Client Secret**: Auth0 application's Client Secret, which you can retrieve from the *Settings* of your application in the [Auth0 Dashboard](${manage_url}/#/applications).
+
+Our implementation should perform a `POST` operation to the `https://${account.namespace}/oauth/token` endpoint with a payload in the following format:
+
+```json
+{
+ "audience": "YOUR_API_IDENTIFIER",
+ "grant_type": "client_credentials",
+ "client_id": "${account.client_id}",
+ "client_secret": "${account.client_secret}"
+}
+```
+
+To learn more, see [API Authorization: Asking for Access Tokens for a Client Credentials Grant](/api-auth/config/asking-for-access-tokens).
+
+::: note
+See the implementation in [Python](/architecture-scenarios/application/server-api/cron-implementation-python#get-an-access-token).
+:::
+
+## Invoke the API
+
+Now that we have an Access Token that includes the valid scopes, we can invoke our API.
+
+To do so, we will:
+- Build a hard-coded timesheet entry in JSON format.
+- Add the Access Token as an `Authorization` header to our request.
+- Make the HTTP POST request.
+- Parse the response, and print it in the terminal (optional).
+
+::: note
+See the implementation in [Python](/architecture-scenarios/application/server-api/cron-implementation-python#invoke-the-api).
+:::
+
+<%= include('./_stepnav', {
+ prev: ["2. Auth0 Configuration", "/architecture-scenarios/server-api/part-2"], next: ["Conclusion", "/architecture-scenarios/server-api/part-4"]
+}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/server-api/part-4.md b/articles/architecture-scenarios/server-api/part-4.md
new file mode 100644
index 0000000000..c0ee98e2bf
--- /dev/null
+++ b/articles/architecture-scenarios/server-api/part-4.md
@@ -0,0 +1,29 @@
+---
+description: Conclusion for the Server + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - server-apps
+ - api-auth
+ - authorization-code
+ - client-credentials
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Server + API: Conclusion
+
+In this document we covered a simple scenario: an API, used to import timesheet entries in ExampleCo's systems, and a cron job, used by external contractors to send in their timesheets using this API.
+
+We learned about the Client Credentials Grant, what an Access Token is, how to configure an API in Auth0, how to configure a Machine to Machine Application to communicate securely with this API, how to define and secure our API endpoints, how to use the provided libraries to validate the Access Token and how to retrieve a new one from Auth0.
+
+We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
+
+We used Node.js for the API implementation and Python for the non interactive server process, hopefully though after going through this document you are able to build this using the technologies you prefer.
+
+<%= include('./_stepnav', {
+ prev: ["3. Application Implementation", "/architecture-scenarios/server-api/part-3"]
+}) %>
diff --git a/articles/architecture-scenarios/application/spa-api/_stepnav.html b/articles/architecture-scenarios/spa-api/_stepnav.html
similarity index 100%
rename from articles/architecture-scenarios/application/spa-api/_stepnav.html
rename to articles/architecture-scenarios/spa-api/_stepnav.html
diff --git a/articles/architecture-scenarios/spa-api/api-implementation-nodejs.md b/articles/architecture-scenarios/spa-api/api-implementation-nodejs.md
new file mode 100644
index 0000000000..6b62c2fa41
--- /dev/null
+++ b/articles/architecture-scenarios/spa-api/api-implementation-nodejs.md
@@ -0,0 +1,256 @@
+---
+title: "SPA + API: Node.js Implementation for the API"
+description: The Node.js implementation of the API for the SPA + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - spa
+ - api-auth
+ - authorization-code
+ - implicit-grant
+ - nodejs
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+# SPA + API: Node.js Implementation for the API
+
+This document is part of the [SPA + API Architecture Scenario](/architecture-scenarios/application/spa-api) and it explains how to implement the API in Node.js. Please refer to the scenario for information on the implemented solution.
+
+::: note
+The full source code for the Node.js API implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).
+:::
+
+## 1. Define the API endpoints
+
+We will use the [Express web application framework](http://expressjs.com/) to build our Node.js API.
+
+### Create a package.json File
+
+Create a folder for your API, navigate into it and run `npm init`. This will setup your `package.json` file.
+
+You can leave the default settings or change them as you see fit.
+
+Our sample's `package.json` looks like the following:
+
+```json
+{
+ "name": "timesheets-api",
+ "version": "1.0.0",
+ "description": "API used to add timesheet entries for employees and contractors",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/auth0-samples/auth0-pnp-timesheets.git"
+ },
+ "author": "Auth0",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/auth0-samples/auth0-pnp-timesheets/issues"
+ },
+ "homepage": "https://github.com/auth0-samples/auth0-pnp-timesheets#readme"
+}
+```
+
+### Install the Dependencies
+
+Next, we need to set our dependencies. We will use the following modules:
+
+- **express**: This module adds the [Express web application framework](https://expressjs.com/).
+
+- **cors**: This module adds support for enabling [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) which is required since the API will be called from a Single-Page Application running on a different domain inside a web browser.
+
+- **jwks-rsa**: This library retrieves RSA signing keys from a **JWKS** (JSON Web Key Set) endpoint. Using `expressJwtSecret` we can generate a secret provider that will provide the right signing key to `express-jwt` based on the `kid` in the JWT header. For more information refer to the [node-jwks-rsa GitHub repository](https://github.com/auth0/node-jwks-rsa).
+
+- **express-jwt**: This module lets you authenticate HTTP requests using JWT tokens in your Node.js applications. It provides several functions that make working with JWTs easier. For more information refer to the [express-jwt GitHub repository](https://github.com/auth0/express-jwt).
+
+- **body-parser**: This is a Node.js body parsing middleware. It extracts the entire body portion of an incoming request stream and exposes it on `req.body` as something easier to interface with. For more information and several alternatives refer to the body-parser GitHub repository.
+
+To install these dependencies run the following:
+
+```bash
+npm install express cors express-jwt jwks-rsa body-parser express-jwt-authz --save
+```
+
+### Implement the Endpoints
+
+Navigate to your API directory and create a `server.js` file. Your code needs to:
+
+- Get the dependencies.
+- Implement the endpoint(s).
+- Launch the API server.
+
+This is our sample implementation:
+
+```js
+const express = require('express');
+const app = express();
+const jwt = require('express-jwt');
+const jwksRsa = require('jwks-rsa');
+const cors = require('cors');
+const bodyParser = require('body-parser');
+
+// Enable CORS
+app.use(cors());
+
+// Enable the use of request body parsing middleware
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({
+ extended: true
+}));
+
+// Create timesheets API endpoint
+app.post('/timesheets', function(req, res){
+ res.status(201).send({message: "This is the POST /timesheets endpoint"});
+})
+
+// Launch the API Server at localhost:8080
+app.listen(8080);
+```
+
+Launch your API server using `node server` and make an HTTP POST request to `localhost:8080/timesheets`. You should see a JSON response with the message `This is the POST /timesheets endpoint`.
+
+So now we have our endpoint but anyone can call it. Continue to the next paragraph to see how we can fix this.
+
+## 2. Secure the API endpoints
+
+In order to validate our token we will use the `jwt` function, provided by the [express-jwt middleware](https://github.com/auth0/express-jwt#usage), and the `jwks-rsa` to retrieve our secret. The libraries do the following:
+
+1. `express-jwt` will decode the token and pass the request, the header and the payload to `jwksRsa.expressJwtSecret`.
+
+1. `jwks-rsa` will then download all signing keys from the JWKS endpoint and see if a one of the signing keys matches the `kid` in the header of the JWT. If none of the signing keys match the incoming `kid`, an error will be thrown. If we have a match, we will pass the right signing key to `express-jwt`.
+
+1. `express-jwt` will the continue its own logic to validate the signature of the token, the expiration, `audience` and the `issuer`.
+
+The steps we will follow in our code are:
+
+- Create the middleware function to validate the Access Token.
+- Enable the use of the middleware in our routes.
+
+You can also write some code to actually save the timesheet to a database. This is our sample implementation (some code is omitted for brevity):
+
+```js
+// set dependencies - code omitted
+
+// Enable CORS - code omitted
+
+// Create middleware for checking the JWT
+const checkJwt = jwt({
+ // Dynamically provide a signing key based on the kid in the header and the signing keys provided by the JWKS endpoint
+ secret: jwksRsa.expressJwtSecret({
+ cache: true,
+ rateLimit: true,
+ jwksRequestsPerMinute: 5,
+ jwksUri: `https://${account.namespace}/.well-known/jwks.json`
+ }),
+
+ // Validate the audience and the issuer
+ audience: '{YOUR_API_IDENTIFIER}', //replace with your API's audience, available at Dashboard > APIs
+ issuer: 'https://${account.namespace}/',
+ algorithms: [ 'RS256' ]
+});
+
+// Enable the use of request body parsing middleware - code omitted
+
+// create timesheets API endpoint - code omitted
+app.post('/timesheets', checkJwt, function(req, res){
+ var timesheet = req.body;
+
+ // Save the timesheet to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+});
+// launch the API Server at localhost:8080 - code omitted
+```
+
+If we launch our server now and do an HTTP POST to `localhost:8080/timesheets` we should get the error message `Missing or invalid token` (which is perfectly fine since we didn’t send an Access Token in our request).
+
+In order to test the working scenario as well we need to:
+
+- Get an Access Token. For details on how to do so refer to: [Get an Access Token](/architecture-scenarios/application/server-api#get-an-access-token).
+- Invoke the API while adding an `Authorization` header to our request with the value `Bearer ACCESS_TOKEN` (where *ACCESS_TOKEN* is the value of the token we retrieved in the first step).
+
+## 3. Check the application permissions
+
+In this step we will add to our implementation the ability to check if the application has permissions (or `scope`) to use our endpoint in order to create a timesheet. In particular we want to ensure that the token has the correct scope, which is `batch:upload`.
+
+In order to do this we will make use of the `express-jwt-authz` Node.js package, so go ahead and add that to your project:
+
+```bash
+npm install express-jwt-authz --save
+```
+
+Now it is as simple as adding a call to `jwtAuthz(...)` to your middleware to ensure that the JWT contain a particular scope in order to execute a particular endpoint.
+
+The **express-jwt-authz** library, which is used in conjunction with express-jwt, validates the [JWT](/tokens/concepts/jwts) and ensures it bears the correct permissions to call the desired endpoint. For more information refer to the [express-jwt-authz GitHub repository](https://github.com/auth0/express-jwt-authz).
+
+This is our sample implementation (some code is omitted for brevity):
+
+```js
+// set dependencies - existing code omitted
+const jwtAuthz = require('express-jwt-authz');
+
+// Enable CORS - code omitted
+
+// Create middleware for checking the JWT - code omitted
+
+// Enable the use of request body parsing middleware - code omitted
+
+// create timesheets API endpoint
+app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets']), function(req, res){
+ var timesheet = req.body;
+
+ // Save the timesheet to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+})
+
+// launch the API Server at localhost:8080 - code omitted
+```
+
+If we invoke our API with a token that does not include this scope we should get the error message Forbidden with the HTTP status code `403`. You can test this by removing this scope from your API.
+
+## 4. Determine the User Identity
+
+The `express-jwt` middleware which is used to validate the JWT, also sets the `req.user` with the information contained in the JWT. If you want to use the `sub` claim to identify the user uniquely, you can simply use `req.user.sub`.
+
+In the case of the timesheets application however, we want to use the email address of the user as the unique identifier.
+
+The first thing we need to do is to write a rule which will add the email address of the user to the Access Token. Go to the [Rules section](${manage_url}/#/rules}) of the Dashboard and click on the __Create Rule__ button.
+
+You can give the rule a descriptive name, for example `Add email to Access Token`, and then use the following code for the rule:
+
+```js
+function (user, context, callback) {
+ const namespace = 'https://api.exampleco.com/';
+ context.accessToken[namespace + 'email'] = user.email;
+ callback(null, user, context);
+}
+```
+
+The `namespace` is used to ensure the claim has a unique name and does not clash with the names of any of the standard OIDC claims. For more info on namespaced claims, refer to [Namespacing Claims](/tokens/guides/create-namespaced-custom-claims).
+
+Now, inside your API, you can retrieve the value of the claim from `req.user`, and use that as the unique user identity which you can associate with timesheet entries.
+
+```js
+app.post('/timesheets', checkJwt, jwtAuthz(['create:timesheets']), function(req, res){
+
+ var timesheet = req.body;
+
+ // Associate the timesheet entry with the current user
+ var userId = req.user['https://api.exampleco.com/email'];
+ timesheet.user_id = userId;
+
+ // Save the timesheet to the database...
+
+ //send the response
+ res.status(201).send(timesheet);
+});
+```
diff --git a/articles/architecture-scenarios/spa-api/index.md b/articles/architecture-scenarios/spa-api/index.md
new file mode 100644
index 0000000000..a91e1b8f87
--- /dev/null
+++ b/articles/architecture-scenarios/spa-api/index.md
@@ -0,0 +1,57 @@
+---
+order: 03
+title: SPA + API
+image: /media/articles/architecture-scenarios/spa-api.png
+extract: Single-Page Web Application which talks to an API. The application will use OpenID Connect (OIDC) with the Implicit Grant Flow to authenticate users with Auth0.
+description: Explains the architecture scenario where a Single-Page Web Application (SPA) talks to an API using OpenID Connect (OIDC), and the OAuth 2.0 Implicit Grant Flow, to authenticate users with Auth0.
+toc: true
+topics:
+ - architecture
+ - spa
+ - api-auth
+ - authorization-code
+ - implicit-grant
+contentType:
+ - tutorial
+ - index
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# SPA + API
+
+In this scenario, we will build a Timesheet API for a fictitious company named ExampleCo. The API will allow adding timesheet entries for an employee or a contractor.
+
+We will also be building a Single-Page Application (SPA) which will be used to log timesheet entries and send them to the centralized timesheet database using the API.
+
+::: panel TL;DR
+* Auth0 provides API Authentication and Authorization as a means to secure access to API endpoints (see [API Authentication and Authorization](/architecture-scenarios/spa-api/part-1#api-authentication-and-authorization))
+* For authorizing a user of a SPA, Auth0 supports the Implicit Grant (see [Implicit Grant](/architecture-scenarios/spa-api/part-1#implicit-grant))
+* Both the SPA and the API must be configured in the Auth0 Dashboard (see [Auth0 Configuration](/architecture-scenarios/spa-api/part-2#auth0-configuration))
+* User Permissions can be enforced using the Authorization Extension (see [Configure the Authorization Extension](/architecture-scenarios/spa-api/part-2#configure-the-authorization-extension))
+* The API will be secured by ensuring that a valid Access Token is passed in the HTTP Authorization header when calls are made to the API (see [Implement the API](/architecture-scenarios/spa-api/part-3#implement-the-api))
+* The Auth0.js library can be used to authorize the user of the SPA and obtain a valid Access Token which can be used to call the API (see [Authorize the User](/architecture-scenarios/spa-api/part-3#authorize-the-user))
+* The SPA can pass the Access Token in the HTTP Authorization header when making calls to the API (see [Call the API](/architecture-scenarios/spa-api/part-3#call-the-api))
+* The SPA can display UI elements conditionally based on scopes granted to user (see [Display UI Elements Conditionally Based on Scope](/architecture-scenarios/spa-api/part-3#display-ui-elements-conditionally-based-on-scope))
+
+:::
+
+## The Premise
+
+ExampleCo is a consulting startup company. Currently, they have approximately 100 employees and they also outsource several activities to external contractors. All employees and external contractors are required to fill in their timesheets every week.
+
+The company has built a timesheets application, a scenario we covered in [Single Sign-On for Regular Web Apps](/architecture-scenarios/web-app-sso). The internal employees use this web app to fill in their timesheets but the company wants to replace it with a SPA. The app will be used to log timesheet entries and send the data to the centralized timesheet database using the API. The app will also allow managers to approve timesheet entries.
+
+## Goals & Requirements
+
+ExampleCo wants to build a flexible solution. At the moment only a SPA is required to capture timesheet entries but in the future, the company plans on launching more applications, like a mobile app to accommodate their sales teams. Hence the company has decided to develop a single Timesheets API which will be used to log time not only by this server process but by all future applications as well. They want to put in place a security architecture that is flexible enough to accommodate this. ExampleCo wants to ensure that a large part of the code and business logic for the application can be shared across the different applications.
+
+It is required that only authorized users and applications are allowed access to the Timesheets API.
+
+Two kinds of users will use this SPA: employees and managers. The employees should be able to read, create and delete their own timesheet entries, while the managers should be able to approve timesheets as well.
+
+<%= include('./_stepnav', {
+ next: ["1. Solution Overview", "/architecture-scenarios/spa-api/part-1"]
+}) %>
diff --git a/articles/architecture-scenarios/spa-api/part-1.md b/articles/architecture-scenarios/spa-api/part-1.md
new file mode 100644
index 0000000000..610b49008e
--- /dev/null
+++ b/articles/architecture-scenarios/spa-api/part-1.md
@@ -0,0 +1,49 @@
+---
+description: Solution Overview for the SPA + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - spa
+ - api-auth
+ - authorization-code
+ - implicit-grant
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# SPA + API: Solution Overview
+
+<%= include('../_includes/_api-overview-of-solution.md') %>
+
+<%= include('../_includes/_api-authentication-and-authorization.md') %>
+
+## Authorization Code Flow with Proof Key for Code Exchange (PKCE)
+
+Because SPAs are public clients and cannot securely store a Client Secret since the source code is available to the browser, you will want to use the [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce) with your SPA.
+
+With this flow, the calling application requests an Access Token over HTTPS with a transformative value—a Code Verifier (or another type of client secret)—that can be verified by the authorization server.
+
+
+## Implicit Flow
+
+The original specifications for OAuth2 introduced the Implicit Flow, a way for SPAs without a backend to obtain Access Tokens and call APIs directly from the browser. However, mitigation strategies are necessary to use the Implicit Flow because tokens are returned in the URL directly from the authorization endpoint as opposed to the token endpoint.
+
+We recommend using the [Authorization Code Flow with PKCE](https://auth0.com/docs/flows/authorization-code-flow) rather than Implicit Flow; however, if you are unable to update to the recommended flow, you should implement necessary mitigations to combat the risks.
+
+## Authorization Extension
+
+The [Auth0 Authorization Extension](/extensions/authorization-extension) allows you to configure Roles, Groups, and Permissions, and assign them to Users.
+
+- The Permissions are actions that someone can do. For ExampleCo's business needs, we will configure four Permissions: read, create, delete and approve timesheets.
+- The Roles are collections of Permissions. ExampleCo's timesheets app will be used by two kinds of users (employees and managers), with different permissions each, so we will configure two Roles: employee and manager.
+
+Since this covers our business case we will not create any Groups.
+
+The Authorization Extension will create a [Rule](/rules) which will read the Roles, Groups, and Permissions assigned to a user and add this information to the [User profile](/rules/current#rule-syntax) during the authentication flow. We can use this information to ensure that the Access Token issued to a user only contains scopes which are allowed. We can later on proceed to customize our app, like disabling the Approve Timesheets functionality if the user does not have the required permission to do so.
+
+<%= include('./_stepnav', {
+ prev: ["Introduction", "/architecture-scenarios/spa-api"], next: ["2. Auth0 Configuration", "/architecture-scenarios/spa-api/part-2"]
+}) %>
diff --git a/articles/architecture-scenarios/spa-api/part-2.md b/articles/architecture-scenarios/spa-api/part-2.md
new file mode 100644
index 0000000000..6b7d8d1299
--- /dev/null
+++ b/articles/architecture-scenarios/spa-api/part-2.md
@@ -0,0 +1,152 @@
+---
+description: Auth0 Configuration for the SPA + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - spa
+ - api-auth
+ - authorization-code
+ - implicit-grant
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# SPA + API: Auth0 Configuration
+
+In this section we will review all the configurations we need to apply at the [Auth0 Dashboard](${manage_url}).
+
+## Create the API
+
+Navigate to the [APIs section](${manage_url}/#/apis) of the dashboard, and click the **Create API** button.
+
+You will be asked to supply the following details for your API:
+
+- __Name__: a friendly name for the API. Does not affect any functionality.
+- __Identifier__: a unique identifier for the API. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all. This value cannot be modified afterwards.
+- __Signing Algorithm__: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting RS256 the token will be signed with the tenant's private key. To learn more about signing algorithms, see [Signing Algorithms](#signing-algorithms).
+
+
+
+Fill in the required information and click the **Create** button.
+
+## Configure the Scopes
+
+Once the application has been created you will need to configure the Scopes which applications can request during authorization.
+
+In the settings for your API, go to the **Scopes** tab. In this section you can add the scopes for our business case: `read:timesheets`, `create:timesheets`, `delete:timesheets`, and `approve:timesheets`.
+
+
+
+## Create the Application
+
+There are four application types in Auth0:
+- __Native App__ (used by mobile or desktop apps),
+- __Single-Page Web App__,
+- __Regular Web App__ and
+- __Machine to Machine App__ (used by CLIs, Daemons, or services running on your backend).
+
+For this scenario we want to create a new Application for our SPA, hence we will use Single-Page Application as the application type.
+
+To create a new Application, navigate to the [dashboard](${manage_url}) and click on the [Applications](${manage_url}/#/applications}) menu option on the left. Click the __+ Create Application__ button.
+
+Set a name for your Application (we will use `Timesheets SPA`) and select `Single-Page Web App` as the type.
+
+Click __Create__.
+
+
+
+That's it for now. When we are done with the SPA implementation we will revisit the dashboard and this Application's settings to make some changes in its configuration.
+
+## Configure the Authorization Extension
+
+You will need to ensure that the Authorization Extension is installed for your tenant. You can refer to the [Authorization Extension documentation](/extensions/authorization-extension#how-to-install) for details on how to do this.
+
+### Define Permissions
+
+You will now define the required Permissions, according to the scopes you have already defined: `read:timesheets`, `create:timesheets`, `delete:timesheets`, and `approve:timesheets`.
+
+In the Authorization Extension, click the **Permissions** tab, and then click on the **Create Permission** button.
+
+In the dialog, capture the details for each permission.
+
+Ensure that the name of the permission is exactly the same as the corresponding scope:
+
+
+
+Proceed to create the permissions for all the remaining scopes:
+
+
+
+### Define Roles
+
+Next let's configure the two Roles: employee and manager.
+
+Head over to the **Roles** tab, click the **Create Role** button, and select the **Timesheets SPA** application.
+
+Set the **Name** and **Description** to `Employee`, and select the `delete:timesheets`, `create:timesheets` and `read:timesheets` permissions. Click on **Save**.
+
+
+
+Next, follow the same process to create a `Manager` role, and ensure that you have selected all the permissions.
+
+
+
+### Assign Users to Roles
+
+You need to assign all users to either the `Manager` or the `Employee` role.
+
+You can do this by going to the **Users** tab in the Authorization Extension and selecting a user.
+
+On the user information screen, go to the **Roles** tab. Click **Add Role to User**, and select the appropriate role.
+
+
+
+### Configuring the Authorization Extension
+
+You will also need to ensure that the Rule for the Authorization Extension is published.
+
+To do so, click on your user avatar in the top right of the Authorization Extension, and select **Configuration**.
+
+
+
+Make sure that **Permissions** are enabled and then click **Publish Rule**.
+
+
+
+### Create a Rule to validate token scopes
+
+The final step in this process is to create a Rule to check if the scopes contained in an Access Token are valid based on the permissions assigned to the user. Any scopes which are not valid for a user should be removed from the Access Token.
+
+In your Auth0 Dashboard, go to the **Rules** tab. You should see the Rule created by the Authorization Extension:
+
+
+
+Click on the **Create Rule** button and select the **Empty Rule** template. You can give the Rule a name, such as **Access Token Scopes**, and then specify the following code for the Rule:
+
+```js
+function (user, context, callback) {
+ var permissions = user.permissions || [];
+ var requestedScopes = context.request.body.scope || context.request.query.scope;
+ var filteredScopes = requestedScopes.split(' ').filter( function(x) {
+ return x.indexOf(':') < 0;
+ });
+
+ var allScopes = filteredScopes.concat(permissions);
+ context.accessToken.scope = allScopes.join(' ');
+
+ callback(null, user, context);
+}
+```
+
+The code above will ensure that all Access Tokens will only contain the properly-formatted scopes (e.g., `action:area` or `delete:timesheets`) which are valid according to a user's permissions. Once you are done you can click on the **Save** button.
+
+Rules execute in the order they are displayed on the Rules page, so ensure that the new rule you created is positioned below the rule for the Authorization Extension, so it executes after the Authorization Extension rule:
+
+
+
+<%= include('./_stepnav', {
+ prev: ["1. Solution Overview", "/architecture-scenarios/spa-api/part-1"], next: ["3. API + SPA Implementation", "/architecture-scenarios/spa-api/part-3"]
+}) %>
diff --git a/articles/architecture-scenarios/spa-api/part-3.md b/articles/architecture-scenarios/spa-api/part-3.md
new file mode 100644
index 0000000000..11ecdf8568
--- /dev/null
+++ b/articles/architecture-scenarios/spa-api/part-3.md
@@ -0,0 +1,215 @@
+---
+description: API and SPA Configuration for the SPA + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - spa
+ - api-auth
+ - authorization-code
+ - implicit-grant
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# SPA + API: API and SPA Configuration
+
+In this section we will see how we can implement an API for our scenario.
+
+::: note
+For simplicity reasons we will keep our implementation solely focused on the authentication and authorization part. As you will see in the samples the input timesheet entry will be hard-coded and the API will not persist the timesheet entry, simply echo back some of the info.
+:::
+
+## Define the API endpoints
+
+First we need to define the endpoints of our API.
+
+::: panel What is an API endpoint?
+An **API endpoint** is a unique URL that represents an object. In order to interact with this object you need to point your application towards that URL. For example, if you had an API that could return either order or customers, you might configure two endpoints: `/orders` and `/customers`. Your application would interact with these endpoints using different HTTP methods, for example `POST /orders` to create a new order, or `GET /orders` to retrieve the dataset of one or more orders.
+:::
+
+For this implementation we will only define 2 endpoints; one for retrieving a list of all timesheets for an employee, and another which will allow an employee to create a new timesheet entry.
+
+An `HTTP GET` request to the `/timesheets` endpoint will allow a user to retrieve their timesheets, and an `HTTP POST` request to the `/timesheets` endpoint will allow a user to add a new timesheet.
+
+::: note
+See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#1-define-the-api-endpoints)
+:::
+
+### Secure the Endpoints
+
+When an API receives a request with a bearer Access Token as part of the header, the first thing to do is to validate the token. This consists of a series of steps, and if any of these fails then the request must be rejected with a `Missing or invalid token` error message to the calling app.
+
+The validations that the API should perform are:
+
+- Check that the JWT is well formed
+- Check the signature
+- Validate the standard claims
+
+::: note
+[JWT.io](https://jwt.io/) provides a list of libraries that can do most of the work for you: parse the JWT, verify the signature and the claims.
+:::
+
+Part of the validation process is to also check the Application permissions (scopes), but we will address this separately in the next paragraph of this document.
+
+For more information on validating Access Tokens, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+
+::: note
+See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#2-secure-the-api-endpoints)
+:::
+
+### Check the Application's Permissions
+
+By now we have verified that the JWT is valid. The last step is to verify that the application has the permissions required to access the protected resources.
+
+To do so, the API needs to check the [scopes](/scopes) of the decoded JWT. This claim is part of the payload and it is a space-separated list of strings.
+
+::: note
+See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#3-check-the-client-permissions)
+:::
+
+### Determine user identity
+
+For both endpoints (retrieving the list of timesheets, and adding a new timesheet) we will need to determine the identity of the user.
+
+For retrieving the list of timesheets this is to ensure that we only return the timesheets belonging to the user making the request, and for adding a new timesheet this is to ensure that the timesheet is associated with the user making the request.
+
+One of the standard JWT claims is the `sub` claim which identifies the principal that is the subject to the claim. In the case of the Implicit Grant flow this claim will contain the user's identity, which will be the unique identifier for the Auth0 user. You can use this to associate any information in external systems with a particular user.
+
+You can also use a custom claim to add another attribute of the user - such as their email address - to the Access Token and use that to uniquely identify the user.
+
+::: note
+See the implementation in [Node.js](/architecture-scenarios/application/spa-api/api-implementation-nodejs#4-determine-the-user-identity)
+:::
+
+## Implement the SPA
+
+In this section we will see how we can implement a SPA for our scenario.
+
+### Authorize the user
+
+To authorize the user we will be using the [auth0.js library](/libraries/auth0js). You can initialize a new instance of the Auth0 application as follows:
+
+```js
+var auth0 = new auth0.WebAuth({
+ clientID: '${account.clientId}',
+ domain: '${account.namespace}',
+ responseType: 'token id_token',
+ audience: 'YOUR_API_IDENTIFIER',
+ redirectUri: '${account.callback}',
+ scope: 'openid profile read:timesheets create:timesheets'
+});
+```
+
+You need to pass the following configuration values:
+
+- __clientID__:The value of your Auth0 Client Id. You can retrieve it from the Settings of your Application at the [Dashboard](${manage_url}/#/applications}).
+- __domain__: The value of your Auth0 Domain. You can retrieve it from the Settings of your Application at the [Dashboard](${manage_url}/#/applications}).
+- __responseType__: Indicates the Authentication Flow to use. For a SPA which uses the __Implicit Flow__, this should be set to `token id_token`. The `token` part, triggers the flow to return an Access Token in the URL fragment, while the `id_token` part, triggers the flow to return an ID Token as well.
+- __audience__: The value of your API Identifier. You can retrieve it from the [Settings of your API](${manage_url}/#/apis}) at the Dashboard.
+- __redirectUri__: The URL to which Auth0 should redirect to after the user has authenticated.
+- __scope__: The [scopes](/scopes) which determine the information to be returned in the ID Token and Access Token. A scope of `openid profile` will return all the user profile information in the ID Token. You also need to request the scopes required to call the API, in this case the `read:timesheets create:timesheets` scopes. This will ensure that the Access Token has these scopes.
+
+To initiate the authentication flow you can call the `authorize()` method:
+
+```js
+auth0.authorize();
+```
+
+After the authentication, Auth0 will redirect back to the __redirectUri__ you specified when configuring the new instance of the Auth0 application. At this point you will need to call the `parseHash()` method which parses a URL hash fragment to extract the result of an Auth0 authentication response.
+
+The contents of the authResult object returned by parseHash depend upon which authentication parameters were used. It may include the following:
+
+- __idToken__: An ID Token JWT containing user profile information
+- __accessToken__: An Access Token for the API, specified by the __audience__.
+- __expiresIn__: A string containing the expiration time (in seconds) of the Access Token.
+
+Determine where best to [store the tokens](/tokens/concepts/token-storage). If your single-page app has a backend server at all, then tokens should be handled server-side using the [Authorization Code Flow](/flows/concepts/auth-code) or [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce).
+
+If you have a single-page app (SPA) with no corresponding backend server, your SPA should request new tokens on login and store them in memory without any persistence. To make API calls, your SPA would then use the in-memory copy of the token.
+
+For an example of how to handle sessions in SPAs, check out the [Handle Authentication Tokens](/quickstart/spa/vanillajs#handle-authentication-tokens) section of the [JavaScript Single-Page App Quickstart](/quickstart/spa/vanillajs).
+
+
+::: note
+See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#2-authorize-the-user)
+:::
+
+### Get the User Profile
+
+::: panel Extract info from the token
+This section shows how to retrieve the user info using the Access Token and the [/userinfo endpoint](/api/authentication#get-user-info). To avoid this API call, you can just decode the ID Token [using a library](https://jwt.io/#libraries-io) (make sure you validate it first). If you need additional user information consider using [our Management API](/api/management/v2#!/Users/get_users_by_id) from your backend.
+:::
+
+The `client.userInfo` method can be called passing the returned `authResult.accessToken` in order to retrieve the user's profile information. It will make a request to the [/userinfo endpoint](/api/authentication#get-user-info) and return the `user` object, which contains the user's information, similar to the example below:
+
+```json
+{
+ "email_verified": "false",
+ "email": "test@example.com",
+ "clientID": "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH",
+ "updated_at": "2017-02-07T20:50:33.563Z",
+ "name": "tester9@example.com",
+ "picture": "https://gravatar.com/avatar/example.png",
+ "user_id": "auth0|123456789012345678901234",
+ "nickname": "tester9",
+ "created_at": "2017-01-20T20:06:05.008Z",
+ "sub": "auth0|123456789012345678901234"
+}
+```
+
+You can access any of these properties in the callback function passed when calling the `userInfo` function:
+
+```js
+const accessToken = authResult.accessToken;
+
+auth0.client.userInfo(accessToken, (err, profile) => {
+ if (profile) {
+ // Get the user’s nickname and profile image
+ var nickname = profile.nickname;
+ var picture = profile.picture;
+ }
+});
+```
+
+::: note
+See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#3-get-the-user-profile).
+:::
+
+### Display UI Elements Conditionally Based on Scope
+
+Based on the `scope` of the user, you may want to show or hide certain UI elements. To determine the scope issued to a user, you will need to store the scope which was initially requested during the authorization process. When a user is authorized, the `scope` will also be returned in the `authResult`.
+
+If the `scope` in the `authResult` is empty, then all the scopes which was requested was granted. If the `scope` in the `authResult` is not empty, it means a different set of scopes were granted, and you should use the ones in `authResult.scope`.
+
+::: note
+See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#4-display-ui-elements-conditionally-based-on-scope)
+:::
+
+### Call the API
+
+To access secured resources from your API, the authenticated user's Access Token needs to be included in requests that are sent to it. This is accomplished by sending the Access Token in an `Authorization` header using the `Bearer` scheme.
+
+::: note
+See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#5-call-the-api)
+:::
+
+### Renew the Access Token
+
+As a security measure, it is recommended that the lifetime of a user's Access Token be kept short. When you create an API in the Auth0 dashboard, the default lifetime is `7200` seconds (2 hours), but this can be controlled on a per-API basis.
+
+Once expired, an Access Token can no longer be used to access an API. In order to obtain access again, a new Access Token needs to be obtained.
+
+Obtaining a new Access Token can be done by repeating the authentication flow, used to obtain the initial Access Token. In a SPA this is not ideal, as you may not want to redirect the user away from their current task to complete the authentication flow again.
+
+In cases like this you can make use of [Silent Authentication](/api-auth/tutorials/silent-authentication). Silent authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page. This does however require that the user was already logged in via [Single Sign-on (SSO)](/sso).
+
+::: note
+See the implementation in [Angular 2](/architecture-scenarios/application/spa-api/spa-implementation-angular2#6-renew-the-access-token)
+:::
+
+<%= include('./_stepnav', {
+ prev: ["2. Auth0 Configuration", "/architecture-scenarios/spa-api/part-2"], next: ["Conclusion", "/architecture-scenarios/spa-api/part-4"]
+}) %>
diff --git a/articles/architecture-scenarios/spa-api/part-4.md b/articles/architecture-scenarios/spa-api/part-4.md
new file mode 100644
index 0000000000..22be4254af
--- /dev/null
+++ b/articles/architecture-scenarios/spa-api/part-4.md
@@ -0,0 +1,29 @@
+---
+description: Conclusion for the SPA + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - spa
+ - api-auth
+ - authorization-code
+ - implicit-grant
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# SPA + API: Conclusion
+
+In this document we covered a simple scenario involving an API used by a Single-Page Application (SPA) to allow employees to capture their timesheets.
+
+We learned about the Implicit Grant, what an Access Token is, how to configure an API in Auth0, how to configure a SPA application to communicate securely with this API, how to define and secure our API endpoints, how to use the provided libraries to validate the Access Token and how to retrieve a new one from Auth0.
+
+We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
+
+We used Node.js for the API implementation and Angular for the SPA. Hopefully though after going through this document you are able to build this using the technologies you prefer.
+
+<%= include('./_stepnav', {
+ prev: ["3. API + SPA Implementation", "/architecture-scenarios/spa-api/part-3"]
+}) %>
\ No newline at end of file
diff --git a/articles/architecture-scenarios/spa-api/spa-implementation-angular2.md b/articles/architecture-scenarios/spa-api/spa-implementation-angular2.md
new file mode 100644
index 0000000000..6d695de9a7
--- /dev/null
+++ b/articles/architecture-scenarios/spa-api/spa-implementation-angular2.md
@@ -0,0 +1,513 @@
+---
+title: "SPA + API: Angular 2 Implementation for the SPA"
+description: The Angular 2 implementation of the SPA for the SPA + API architecture scenario
+toc: true
+topics:
+ - architecture
+ - spa
+ - api-auth
+ - authorization-code
+ - implicit-grant
+ - angular2
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# SPA + API: Angular 2 Implementation for the SPA
+
+This document is part of the [SPA + API Architecture Scenario](/architecture-scenarios/application/spa-api) and it explains how to implement the SPA in Angular 2. Please refer to the scenario for information on the implemented solution.
+
+::: note
+The full source code for the Angular 2 implementation of the SPA can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-spa/angular).
+:::
+
+## 1. Configuration
+
+Your application will require certain configuration information. Before carrying on with the rest of the implementation, create an `AuthConfig` interface which will contain various configuration values. Place this interface in a file called `auth0-variables.ts`.
+
+```js
+interface AuthConfig {
+ clientID: string;
+ domain: string;
+ callbackURL: string;
+ apiUrl: string;
+}
+
+export const AUTH_CONFIG: AuthConfig = {
+ clientID: '',
+ domain: '',
+ callbackURL: 'http://localhost:4200/callback',
+ apiUrl: ''
+};
+```
+
+## 2. Authorize the User
+
+### Create an Authorization Service
+
+The best way to manage and coordinate the tasks necessary for user authentication is to create a reusable service. With the service in place, you'll be able to call its methods throughout your application. An instance of the `WebAuth` object from [auth0.js](/libraries/auth0js) can be created in the service.
+
+```js
+import { Injectable } from '@angular/core';
+import { AUTH_CONFIG } from './auth0-variables';
+import { Router } from '@angular/router';
+import 'rxjs/add/operator/filter';
+import auth0 from 'auth0-js';
+
+@Injectable()
+export class AuthService {
+
+ userProfile: any;
+ requestedScopes: string = 'openid profile read:timesheets create:timesheets';
+
+ auth0 = new auth0.WebAuth({
+ clientID: AUTH_CONFIG.clientID,
+ domain: AUTH_CONFIG.domain,
+ responseType: 'token id_token',
+ audience: AUTH_CONFIG.apiUrl,
+ redirectUri: AUTH_CONFIG.callbackURL,
+ scope: this.requestedScopes
+ });
+
+ constructor(public router: Router) {}
+
+ public login(): void {
+ this.auth0.authorize();
+ }
+
+ public handleAuthentication(): void {
+ this.auth0.parseHash((err, authResult) => {
+ if (authResult && authResult.accessToken && authResult.idToken) {
+ window.location.hash = '';
+ this.setSession(authResult);
+ this.router.navigate(['/home']);
+ } else if (err) {
+ this.router.navigate(['/home']);
+ console.log(err);
+ alert('Error: <%= "${err.error}" %>. Check the console for further details.');
+ }
+ });
+ }
+
+ private setSession(authResult): void {
+ // Set the time that the Access Token will expire at
+ const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
+
+ // If there is a value on the scope param from the authResult,
+ // use it to set scopes in the session for the user. Otherwise
+ // use the scopes as requested. If no scopes were requested,
+ // set it to nothing
+ const scopes = authResult.scope || this.requestedScopes || '';
+
+ localStorage.setItem('access_token', authResult.accessToken);
+ localStorage.setItem('id_token', authResult.idToken);
+ localStorage.setItem('expires_at', expiresAt);
+ localStorage.setItem('scopes', JSON.stringify(scopes));
+ }
+
+ public logout(): void {
+ // Remove tokens and expiry time from localStorage
+ localStorage.removeItem('access_token');
+ localStorage.removeItem('id_token');
+ localStorage.removeItem('expires_at');
+ localStorage.removeItem('scopes');
+ // Go back to the home route
+ this.router.navigate(['/']);
+ }
+
+ public isAuthenticated(): boolean {
+ // Check whether the current time is past the
+ // Access Token's expiry time
+ const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
+ return new Date().getTime() < expiresAt;
+ }
+
+ public userHasScopes(scopes: Array): boolean {
+ const grantedScopes = JSON.parse(localStorage.getItem('scopes')).split(' ');
+ return scopes.every(scope => grantedScopes.includes(scope));
+ }
+}
+```
+
+The service includes several methods for handling authentication.
+
+- __login__: calls `authorize` from auth0.js which initiates [Universal Login](/universal-login)
+- __handleAuthentication__: looks for an authentication result in the URL hash and processes it with the `parseHash` method from auth0.js
+- __setSession__: sets the user's Access Token, ID Token, and a time at which the Access Token will expire
+- __logout__: removes the user's tokens from browser storage
+- __isAuthenticated__: checks whether the expiry time for the Access Token has passed
+
+### Process the Authentication Result
+
+When a user authenticates via Universal Login and is then redirected back to your application, their authentication information will be contained in a URL hash fragment. The `handleAuthentication` method in the `AuthService` is responsible for processing the hash.
+
+Call `handleAuthentication` in your app's root component so that the authentication hash fragment can be processed when the app first loads after the user is redirected back to it.
+
+```js
+// src/app/app.component.ts
+
+import { Component } from '@angular/core';
+import { AuthService } from './auth/auth.service';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+
+export class AppComponent {
+
+ constructor(public auth: AuthService) {
+ auth.handleAuthentication();
+ }
+}
+```
+
+### Add the Callback Component
+
+Using Universal Login means that users are taken away from your application to a page hosted by Auth0. After they successfully authenticate, they are returned to your application where a client-side session is set for them.
+
+You can choose to have users return to any URL in your application that you like; however, it is recommended that you create a dedicated callback route to serve as a central location that the user will be returned to upon successful authentication. Having a single callback route is beneficial for two main reasons:
+
+- It prevents the need to whitelist multiple (and sometimes unknown) callback URLs
+- It serves as a place to show a loading indicator while your application sets the user's client-side session
+
+Create a component named `CallbackComponent` and populate it with a loading indicator.
+
+```html
+
+
+
+
+
+```
+
+::: note
+This example assumes some kind of loading spinner is available in an `assets` directory. See the downloadable sample for a demonstration.
+:::
+
+After authentication, users will be taken to the `/callback` route for a brief time where they will be shown a loading indicator. During this time, their client-side session will be set, after which they will be redirected to the `/home` route.
+
+## 3. Get the User Profile
+
+::: panel Extract info from the token
+This section shows how to retrieve the user info using the Access Token and the [/userinfo endpoint](/api/authentication#get-user-info). Alternatively, you can just decode the ID Token [using a library](https://jwt.io/#libraries-io) (make sure you validate it first). The output will be the same. If you need additional user information consider using the [our Management API](/api/management/v2#!/Users/get_users_by_id).
+:::
+
+To obtain the user's profile, update the existing `AuthService` class. Add a `getProfile` function which will extract the user's Access Token from local storage, and then pass that call the `userInfo` function to retrieve the user's information.
+
+```js
+// Existing code from the AuthService class is omitted in this code sample for brevity
+@Injectable()
+export class AuthService {
+ public getProfile(cb): void {
+ const accessToken = localStorage.getItem('access_token');
+ if (!accessToken) {
+ throw new Error('Access Token must exist to fetch profile');
+ }
+
+ const self = this;
+ this.auth0.client.userInfo(accessToken, (err, profile) => {
+ if (profile) {
+ self.userProfile = profile;
+ }
+ cb(err, profile);
+ });
+ }
+}
+```
+
+You can now simply call this function from any service where you want to retrieve and display information about the user.
+
+For example you may choose to create a new component to display the user's profile information:
+
+```js
+import { Component, OnInit } from '@angular/core';
+import { AuthService } from './../auth/auth.service';
+
+@Component({
+ selector: 'app-profile',
+ templateUrl: './profile.component.html',
+ styleUrls: ['./profile.component.css']
+})
+export class ProfileComponent implements OnInit {
+
+ profile: any;
+
+ constructor(public auth: AuthService) { }
+
+ ngOnInit() {
+ if (this.auth.userProfile) {
+ this.profile = this.auth.userProfile;
+ } else {
+ this.auth.getProfile((err, profile) => {
+ this.profile = profile;
+ });
+ }
+ }
+}
+```
+
+The template for this component looks as follows:
+
+```html
+
+
+
Profile
+
+
+
+
+
+
{{ profile?.nickname }}
+
+
{{ profile | json }}
+
+
+```
+
+## 4. Display UI Elements Conditionally Based on Scope
+
+During the authorization process we already stored the actual scopes which a user was granted in the local storage. If the `scope` returned in the `authResult` is not empty, it means that a user was issued a different set of scopes than what was initially requested, and we should therefore use `authResult.scope` to determine the scopes granted to the user.
+
+If the `scope` returned in `authResult` is issued is empty, it means the user was granted all the scopes that were requested, and we can therefore use the requested scopes to determine the scopes granted to the user.
+
+Here is the code we wrote earlier for the `setSession` function that does that check:
+
+```js
+private setSession(authResult): void {
+ // Set the time that the Access Token will expire at
+ const expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
+
+ // If there is a value on the `scope` param from the authResult,
+ // use it to set scopes in the session for the user. Otherwise
+ // use the scopes as requested. If no scopes were requested,
+ // set it to nothing
+ const scopes = authResult.scope || this.requestedScopes || '';
+
+ localStorage.setItem('access_token', authResult.accessToken);
+ localStorage.setItem('id_token', authResult.idToken);
+ localStorage.setItem('expires_at', expiresAt);
+ localStorage.setItem('scopes', JSON.stringify(scopes));
+ this.scheduleRenewal();
+}
+```
+
+Next we need to add a function to the `AuthService` class which we can call to determine if a user was granted a specific scope:
+
+```js
+@Injectable()
+export class AuthService {
+ // some code omitted for brevity
+
+ public userHasScopes(scopes: Array): boolean {
+ const grantedScopes = JSON.parse(localStorage.getItem('scopes')).split(' ');
+ return scopes.every(scope => grantedScopes.includes(scope));
+ }
+}
+```
+
+You can call this method to determine whether we should display a specific UI element, or not. As an example we only want to display the **Approve Timesheets** link if the user has the `approve:timesheets` scope. Note in the code below that we added a call to the `userHasScopes` function to determine whether that link should be displayed or not.
+
+```html
+
+
+
+
+
+```
+
+### Protect a route
+
+We should also protect a route to not allow a route to be navigated to if a user has not been granted the correct scopes. For this we can add a new `ScopeGuardService` service class:
+
+```js
+import { Injectable } from '@angular/core';
+import { Router, CanActivate, ActivatedRouteSnapshot } from '@angular/router';
+import { AuthService } from './auth.service';
+
+@Injectable()
+export class ScopeGuardService implements CanActivate {
+
+ constructor(public auth: AuthService, public router: Router) {}
+
+ canActivate(route: ActivatedRouteSnapshot): boolean {
+
+ const scopes = (route.data as any).expectedScopes;
+
+ if (!this.auth.isAuthenticated() || !this.auth.userHasScopes(scopes)) {
+ this.router.navigate(['']);
+ return false;
+ }
+ return true;
+ }
+
+}
+```
+
+And then use that when we configure the routes to determine whether a route can be activated. Notice the use of the new `ScopeGuardService` in the definition for the `approval` route below:
+
+
+```js
+// app.routes.ts
+
+import { Routes, CanActivate } from '@angular/router';
+import { HomeComponent } from './home/home.component';
+import { ProfileComponent } from './profile/profile.component';
+import { CallbackComponent } from './callback/callback.component';
+import { AuthGuardService as AuthGuard } from './auth/auth-guard.service';
+import { ScopeGuardService as ScopeGuard } from './auth/scope-guard.service';
+import { TimesheetListComponent } from './timesheet-list/timesheet-list.component';
+import { TimesheetAddComponent } from './timesheet-add/timesheet-add.component';
+import { ApprovalComponent } from './approval/approval.component';
+
+export const ROUTES: Routes = [
+ { path: '', component: HomeComponent },
+ { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
+ { path: 'callback', component: CallbackComponent },
+ { path: 'timesheets/add', component: TimesheetAddComponent, canActivate: [AuthGuard] },
+ { path: 'timesheets', component: TimesheetListComponent, canActivate: [AuthGuard] },
+ { path: 'approval', component: ApprovalComponent, canActivate: [ScopeGuard], data: { expectedScopes: ['approve:timesheets']} },
+ { path: '**', redirectTo: '' }
+];
+```
+
+## 5. Call the API
+
+The [angular2-jwt](https://github.com/auth0/angular2-jwt) module can be used to automatically attach JSON Web Tokens to requests made to your API. It does this by providing an `AuthHttp` class which is a wrapper over Angular's `Http` class.
+
+Install `angular2-jwt`:
+
+```text
+# installation with npm
+npm install --save angular2-jwt
+
+# installation with yarn
+yarn add angular2-jwt
+```
+
+Create a factory function with some configuration values for `angular2-jwt` and add it to the `providers` array in your application's `@NgModule`. The factory function should have a `tokenGetter` function which fetches the `access_token` from local storage.
+
+```js
+import { Http, RequestOptions } from '@angular/http';
+import { AuthHttp, AuthConfig } from 'angular2-jwt';
+
+export function authHttpServiceFactory(http: Http, options: RequestOptions) {
+ return new AuthHttp(new AuthConfig({
+ tokenGetter: (() => localStorage.getItem('access_token'))
+ }), http, options);
+}
+
+@NgModule({
+ declarations: [...],
+ imports: [...],
+ providers: [
+ AuthService,
+ {
+ provide: AuthHttp,
+ useFactory: authHttpServiceFactory,
+ deps: [Http, RequestOptions]
+ }
+ ],
+ bootstrap: [...]
+})
+```
+
+After `angular2-jwt` is configured, you can use the `AuthHttp` class to make secure calls to your API from anywhere in the application. To do so, inject `AuthHttp` in any component or service where it is needed and use it just as you would use Angular's regular `Http` class.
+
+```js
+import { Injectable } from '@angular/core';
+import { Http } from '@angular/http';
+import { AuthHttp } from 'angular2-jwt';
+import 'rxjs/add/operator/map';
+import { NewTimesheetModel } from '../models/new-timesheet-model';
+
+@Injectable()
+export class TimesheetsService {
+
+ constructor(public authHttp: AuthHttp) { }
+
+ addTimesheet(model: NewTimesheetModel) {
+ return this.authHttp.post('http://localhost:8080/timesheets', JSON.stringify(model));
+ }
+
+ getAllTimesheets() {
+ return this.authHttp.get('http://localhost:8080/timesheets')
+ .map(res => res.json())
+ }
+}
+```
+
+## 6. Renew the Access Token
+
+Renewing the user's Access Token requires to update the Angular SPA. Add a method to the `AuthService` which calls the `checkSession` method from auth0.js. If the renewal is successful, use the existing `setSession` method to set the new tokens in local storage.
+
+```js
+public renewToken() {
+ this.auth0.checkSession({
+ audience: AUTH_CONFIG.apiUrl
+ }, (err, result) => {
+ if (!err) {
+ this.setSession(result);
+ }
+ });
+}
+```
+
+In the `AuthService` class, add a method called `scheduleRenewal` to set up a time at which authentication should be silently renewed. In the sample below this is set up to happen 30 seconds before the actual token expires. Also add a method called `unscheduleRenewal` which will unsubscribe from the Observable.
+
+```js
+public scheduleRenewal() {
+ if (!this.isAuthenticated()) return;
+
+ const expiresAt = JSON.parse(window.localStorage.getItem('expires_at'));
+
+ const source = Observable.of(expiresAt).flatMap(
+ expiresAt => {
+
+ const now = Date.now();
+
+ // Use the delay in a timer to
+ // run the refresh at the proper time
+ var refreshAt = expiresAt - (1000 * 30); // Refresh 30 seconds before expiry
+ return Observable.timer(Math.max(1, refreshAt - now));
+ });
+
+ // Once the delay time from above is
+ // reached, get a new JWT and schedule
+ // additional refreshes
+ this.refreshSubscription = source.subscribe(() => {
+ this.renewToken();
+ });
+}
+
+public unscheduleRenewal() {
+ if (!this.refreshSubscription) return;
+ this.refreshSubscription.unsubscribe();
+}
+```
+
+Finally you need to initiate the schedule renewal. This can be done by calling `scheduleRenewal` inside your `AppComponent` which will happen when the page is loaded. This will occur after every authentication flow, either when the user explicitly logs in, or when the silent authentication happens.
+
+<%= include('../../_includes/_refresh_token_rotation_recommended.md') %>
diff --git a/articles/architecture-scenarios/application/web-app-sso/_stepnav.html b/articles/architecture-scenarios/web-app-sso/_stepnav.html
similarity index 100%
rename from articles/architecture-scenarios/application/web-app-sso/_stepnav.html
rename to articles/architecture-scenarios/web-app-sso/_stepnav.html
diff --git a/articles/architecture-scenarios/web-app-sso/implementation-aspnetcore.md b/articles/architecture-scenarios/web-app-sso/implementation-aspnetcore.md
new file mode 100644
index 0000000000..97414fc9e7
--- /dev/null
+++ b/articles/architecture-scenarios/web-app-sso/implementation-aspnetcore.md
@@ -0,0 +1,188 @@
+---
+title: "SSO for Regular Web Apps: ASP.NET Core Implementation"
+description: The ASP.NET Core implementation for the Single Sign-on (SSO) for Regular Web Apps architecture scenario
+topics:
+ - architecture
+ - regular-web-apps
+ - api-auth
+ - authorization-code
+ - lockjs
+ - aspnetcore
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Single Sign-On (SSO) for Regular Web Apps: ASP.NET Core implementation
+
+Full source code for the ASP.NET Core implementation can be found in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-webapp-oidc).
+
+## Configure the Cookie and OIDC Middleware
+
+For the purposes this guide we will be using a simple hosted login. You can use the standard cookie and OIDC middleware which is available with ASP.NET Core, so ensure that you install the NuGet packages.
+
+```text
+Install-Package Microsoft.AspNetCore.Authentication.Cookies
+Install-Package Microsoft.AspNetCore.Authentication.OpenIdConnect
+```
+
+Then configure the cookie and OIDC middleware inside your application's middleware pipeline.
+
+```csharp
+public class Startup
+{
+ public void ConfigureServices(IServiceCollection services)
+ {
+ // Add authentication services
+ services.AddAuthentication(
+ options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
+
+ // Code omitted for brevity...
+ }
+
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions auth0Settings)
+ {
+ // Code omitted for brevity...
+
+ // Add the cookie middleware
+ app.UseCookieAuthentication(new CookieAuthenticationOptions
+ {
+ AutomaticAuthenticate = true,
+ AutomaticChallenge = true
+ });
+
+ // Add the OIDC middleware
+ app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
+ {
+ // Set the authority to your Auth0 domain
+ Authority = "https://${account.namespace}/",
+
+ // Configure the Auth0 Client ID and Client Secret
+ ClientId = ${account.clientId},
+ ClientSecret = YOUR_CLIENT_SECRET,
+
+ // Do not automatically authenticate and challenge
+ AutomaticAuthenticate = false,
+ AutomaticChallenge = false,
+
+ // Set response type to code
+ ResponseType = "code",
+
+ CallbackPath = new PathString("/signin-auth0"),
+
+ // Configure the Claims Issuer to be Auth0
+ ClaimsIssuer = "Auth0"
+ });
+
+ // Code omitted for brevity...
+ }
+}
+```
+
+As you can see in the code above, we have configured two different types of authentication middleware.
+
+The first is the cookie middleware which was registered with the call to `UseCookieAuthentication`.
+The second is the OIDC middleware which is done with the call to `UseOpenIdConnectAuthentication`.
+
+Once the user has signed in to Auth0 using the OIDC middleware, their information will automatically be stored inside a session cookie. All you need to do is to configure the middleware as above and it will take care of managing the user session.
+
+The OpenID Connect (OIDC) middleware will also extract all the claims from the ID Token, which is sent from Auth0 once the user has authenticated, and add them as claims on the `ClaimsIdentity`.
+
+## Implement the Logout
+
+You can control both the application session and the Auth0 session using the `SignOutAsync` method of the `AuthenticationManager` class, and passing along the authentication scheme from which you want to sign out.
+
+As an example to sign out of the cookie middleware, and thereby clearing the authentication cookie for your application, you can make the following call:
+
+```csharp
+await HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
+```
+
+Similarly you can log the user out from Auth0 by making a call to the `SignOutAsync` method and passing along `Auth0` as the authentication scheme to sign out of.
+
+```csharp
+await HttpContext.Authentication.SignOutAsync("Auth0");
+```
+
+For the above to work you will however also need to add extra configuration when registering the OIDC middleware by handling the `OnRedirectToIdentityProviderForSignOut` event. Inside the event you will need to redirect to the [Auth0 logout endpoint](/api/authentication/reference#logout) which will clear the Auth0 cookie.
+
+```csharp
+app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
+{
+ // Some code omitted for brevity
+ Events = new OpenIdConnectEvents
+ {
+ OnRedirectToIdentityProviderForSignOut = context =>
+ {
+ context.Response.Redirect($"https://{auth0Settings.Value.Domain}/v2/logout?client_id={auth0Settings.Value.ClientId}&returnTo={context.Request.Scheme}://{context.Request.Host}/");
+ context.HandleResponse();
+
+ return Task.FromResult(0);
+ }
+ }
+});
+```
+
+You will also need to ensure that you add your application's URL to the __Allowed Logout URLs__ for your application inside the Auth0 dashboard. For more information refer to [Logout](/logout).
+
+## Implement Admin permissions
+
+The easiest way to integrate the groups into an ASP.NET Core application is to use the built-in [Role-based Authorization](https://docs.asp.net/en/latest/security/authorization/roles.html) available in ASP.NET Core. In order to achieve this we will need to add a Claim of type
+
+```text
+http://schemas.microsoft.com/ws/2008/06/identity/claims/role
+```
+
+for each of the groups a user is assigned to.
+
+Once the claims has been added we can easily ensure that a specific action is available only to `Admin` users by decorating the claim with the `[Authorize(Roles = "Admin")]` attribute. You can also check whether a user is in a specific role from code by making a call to `User.IsInRole("Admin")` from inside your controller.
+
+The ASP.NET OIDC middleware will automatically add all claims returned in the JWT as claims to the `ClaimsIdentity`. We would therefore need to extract the information from the `authorization` claim, deserialize the JSON body of the claim, and for each of the groups add a `http://schemas.microsoft.com/ws/2008/06/identity/claims/role` claim to the `ClaimsIdentity`.
+
+```csharp
+app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions("Auth0")
+{
+ // Some configuration omitted for brevity
+
+ Events = new OpenIdConnectEvents
+ {
+ OnTicketReceived = context =>
+ {
+ var options = context.Options as OpenIdConnectOptions;
+
+ // Get the ClaimsIdentity
+ var identity = context.Principal.Identity as ClaimsIdentity;
+ if (identity != null)
+ {
+ // Add the groups as roles
+ var authzClaim = context.Principal.FindFirst(c => c.Type == "authorization");
+ if (authzClaim != null)
+ {
+ var authorization = JsonConvert.DeserializeObject(authzClaim.Value);
+ if (authorization != null)
+ {
+ foreach (var group in authorization.Groups)
+ {
+ identity.AddClaim(new Claim(ClaimTypes.Role, group, ClaimValueTypes.String, options.Authority));
+ }
+ }
+ }
+ }
+
+ return Task.FromResult(0);
+ }
+ }
+});
+```
+
+And subsequently we can add an action which allows Administrators to approve timesheets:
+
+```csharp
+[Authorize(Roles = "Admin")]
+public IActionResult TimesheetApproval()
+{
+ return View();
+}
+```
diff --git a/articles/architecture-scenarios/web-app-sso/index.md b/articles/architecture-scenarios/web-app-sso/index.md
new file mode 100644
index 0000000000..d62eb21e3e
--- /dev/null
+++ b/articles/architecture-scenarios/web-app-sso/index.md
@@ -0,0 +1,79 @@
+---
+order: 01
+title: Single Sign-On for Regular Web Apps
+image: /media/articles/architecture-scenarios/web-oidc.png
+extract: Traditional web application which needs to authenticate users using OpenID Connect (OIDC).
+description: Regular web app scenario which needs to authenticate users using OpenID Connect (OIDC).
+toc: true
+topics:
+ - architecture
+ - regular-web-apps
+ - api-auth
+ - authorization-code
+ - lockjs
+contentType:
+ - tutorial
+ - index
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Single Sign-On for Regular Web Apps
+
+In this scenario, we will build a web application for a fictitious company named ExampleCo. The app is meant to be used by ExampleCo's employees and contractors. Employees will use their existing corporate directory (Active Directory), while contractors will be managed in a separate user store.
+
+::: panel TL;DR
+* Auth0 supports open standards such as OAuth 2.0 and OpenID Connect (OIDC) for authentication and authorization (see [Which protocol to use](/architecture-scenarios/web-app-sso/part-1#which-protocol-to-use))
+* OIDC supports several different authorization flows - the most appropriate one for Web Applications being the Authorization Code Flow (see [Authentication Flow](/architecture-scenarios/web-app-sso/part-1#authentication-flow))
+* Your application will be configured in Auth0 as an application (see [Application](/architecture-scenarios/web-app-sso/part-2#application))
+* Identity Providers will be configured in Auth0 as a Connection (see [Connections](/architecture-scenarios/web-app-sso/part-2#connections))
+* Auth0 provides a Lock widget, which allow users to log in to the application (see [User Login](/architecture-scenarios/web-app-sso/part-3#user-login))
+* The web application needs to manage session state to keep track of the fact that the user is logged in. Along with this, Auth0 and the Identity Provider is also managing session information. (see [Session Management](/architecture-scenarios/web-app-sso/part-3#session-management))
+* Conversely, logging a user out also involves three layers of session management (see [User Logout](/architecture-scenarios/web-app-sso/part-3#user-logout))
+* Access Control can be managed with the Auth0 Authorization Extension (see [Access Control](/architecture-scenarios/web-app-sso/part-3#access-control))
+:::
+
+::: note
+By _Regular Web App_, we mean an app that uses primarily server side, page `GET`, `POST`, and cookies for maintaining state. This is contrast with a Web _SPA_ (Single-Page App), that heavily relies on client side JavaScript code calling an API.
+:::
+
+## The Premise
+
+ExampleCo is a consulting startup company. Currently they have approximately 100 employees and they also outsource several activities to external contractors. Most of the employees work from the company's main office, but there are some teams that work remotely. Additionally, some employees frequently travel to customer locations and work from mobile devices.
+
+All employees and external contractors are required to fill in their timesheets every week using spreadsheets. The current system is inefficient and the company decided that they need to move to a better and more automated solution.
+
+The company evaluated several of the available timesheets application and concluded that it would be more cost-effective to build their own in-house solution, since they are looking for a very simple application at the moment. The app will be built using ASP.NET Core, since their developers are already using this technology and they can have the app ready in a week or so.
+
+### Goals & Requirements
+
+ExampleCo wants to launch the new solution quickly so they chose to start simple and build into it as they gather feedback from their employees.
+
+The application should be available to logged in users only. Each user will have a role, and based on this role, they should be able to perform certain actions and view specific data.
+
+::: panel Authentication vs Authorization
+ExampleCo wants to __authenticate__ and __authorize__ each user. Authentication has to do with identity: verifying that the user is indeed who they claim to be. Authorization is about deciding which resources a user should have access to, and what they should be allowed to do with those resources.
+:::
+
+ExampleCo's timesheets app needs to support two roles: _User_ and _Admin_:
+- Someone with the User role can add timesheet entries, by specifying the date, the application and the hours worked. The Admin role also has this same right.
+- Those with the User role should have access only to their own timesheets entries.
+- Someone with the Admin role can additionally:
+ - Approve or reject timesheet entries of other users.
+ - Edit the application drop-down list of values (add, edit, delete).
+
+Each user will be required to fill in their timesheets by the end of the week. They can either choose to register daily their timesheets or add the entries for the whole week together. The timesheets will have to be reviewed and approved by an Admin. The rejected entries will have to be updated by each employee and re-submitted for approval.
+
+The company uses Active Directory for all employees and employees will sign into the Timesheet application using their Active Directory credentials. The external contractors can sign in with a username and password. Contractors are not on ExampleCo's corporate directory.
+
+ExampleCo wants to minimize user login burden, but wants to maintain a level of security depending on the operation: submitting timesheet entries is lower risk than approving them. However the approved timesheets are used for customer charging so security is definitely a requirement. The authentication strategy should be flexible so it can adapt as the company grows. For example, they should easily be able to add additional authentication requirements, like multi-factor authentication, for Admins.
+
+The solution should be available both to the employees with a physical presence in the company office, as well as to those working remotely, without the overhead of a VPN connection, hence the app should be deployed on a cloud provider like Heroku or Microsoft Azure.
+
+
+
+<%= include('./_stepnav', {
+ next: ["1. Solution Overview", "/architecture-scenarios/web-app-sso/part-1"]
+}) %>
diff --git a/articles/architecture-scenarios/web-app-sso/part-1.md b/articles/architecture-scenarios/web-app-sso/part-1.md
new file mode 100644
index 0000000000..6bb6ce0c96
--- /dev/null
+++ b/articles/architecture-scenarios/web-app-sso/part-1.md
@@ -0,0 +1,105 @@
+---
+description: Regular web app scenario solution overview
+toc: true
+topics:
+ - architecture
+ - regular-web-apps
+ - api-auth
+ - authorization-code
+ - lockjs
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Single Sign-On for Regular Web Apps: Solution Overview
+
+In this section, we'll cover the solution we're implementing, including details on identity management, protocols to use, and the authentication flow required.
+
+## Identity Management
+
+ExampleCo decided to use Auth0 as their Identity as a Service (IDaaS) provider. The reasoning behind this decision was that the company did not want to commit resources on training, implementation and maintenance of identity and access management. Furthermore, the company plans on building into this solution in the future, possibly adding a mobile native app and an API to push approved timesheets to their internal systems. Auth0 provides the flexibility to incorporate such changes in their architecture with minimum effort.
+
+::: note
+Identity-as-Service ("IDaaS") is a cloud-based service for identity and access management. The offered services often include Single Sign-on (SSO), federated identity, password management, and more.
+:::
+
+## Which protocol to use
+
+The next decision has to do with which protocol to use, OAuth 2.0 with OpenID Connect (OIDC) or SAML.
+
+::: note
+Auth0 implements proven, common and popular identity protocols, both for consumer oriented web products (OAuth 2.0, OAuth 1.0, OpenID) and for enterprise deployments (SAML, WS-Federation, LDAP). You have complete freedom to use the one that best meets your business needs.
+:::
+
+__OpenID Connect__ is an authentication protocol, based on the OAuth 2.0 family of specifications. It uses simple JSON identity tokens (JWT) delivered via the OAuth 2.0 protocol.
+
+::: panel OAuth vs OpenID Connect (OIDC)
+OAuth 2.0 and OpenID Connect (OIDC) are often mistaken for the same thing, but this is not exact.
+__OAuth 2.0__ is a protocol that lets you authorize one website (the consumer or application) to access your data from another website (the resource server or provider). For example, you want to authorize a website to access some files from your Dropbox account. The website will redirect you to Dropbox which will ask you whether it should provide access to your files. If you agree the website will be authorized to access your files from Dropbox. At the core, OAuth 2.0 is about resource access and sharing.
+__OpenID Connect__, on the other hand, is a simple identity layer built on top of the OAuth 2.0 protocol. It gives you one login for multiple sites. Each time you need to log in to a website using OIDC, you are redirected to your OpenID site where you login, and then taken back to the website. At the core, OIDC is concerned with user authentication.
+:::
+
+__SAML__ is an XML-based protocol, that provides both authentication and authorization between trusted parties.
+
+Compared to SAML, OpenID Connect is lighter weight and simpler to deal with. SAML is proven, powerful and flexible, but for the requirements of this app, that flexibility and power is not required. Identity federation (one of the most compelling reasons for adopting SAML) is not required here either, And if it ever became a requirement, it can be easily handled by Auth0, in the same way it deals with AD (that uses LDAP).
+
+For these reasons, ExampleCo will use OpenID Connect for their implementation.
+
+## Authentication Flow
+
+OpenID Connect supports more than one flow for authentication. Since our scenario involves a regular web app we will use the __Authorization Code Flow__.
+
+The flow goes as follows:
+1. The web app (called the __Client__ in OIDC terms) initiates the authentication request by redirecting the __user-agent__ (browser) to Auth0 (the __Authorization Server__ in OIDC terms).
+1. Auth0 authenticates the user (via the user-agent). The first time the user goes through this flow a consent page will be shown where the permissions that will be given to the Application are listed (for example, post messages, list contacts). The user logs in to the service (unless they are already logged in) and authorizes the application access.
+1. Assuming the user grants access, Auth0 redirects the __user-agent__ back to the __Application__, along with an _authorization code_ in the query string.
+1. The Application sends the _authorization code_ to Auth0, along with the application credentials (`client_id` and `client_secret`), and asks for a token.
+1. Auth0 authenticates the __Application__ (using the `client_id` and `client_secret`) and validates the _authorization code_. If valid, Auth0 responds back with an __ID Token__.
+
+
+
+::: panel Form Post Response Mode
+Another option is to use the __OAuth 2.0 Form Post Response Mode__ with `response_type=id_token&response_mode=form_post`. Due to the `response_type=id_token` request parameter, the response contains the ID Token directly, instead of the authorization code, while the `response_mode=form_post` encodes the ID Token with the rest of the Authorization Response parameters as HTML form values that are auto-submitted in the User Agent. This way you can have an optimized authentication flow (no need to exchange the code for an ID Token), however you have to make sure that it is supported by the technology you are using to implement your app (ASP .NET Core middleware does support it). For more details refer to the [OAuth 2.0 Form Post Response Mode specification](https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html).
+:::
+
+The __ID Token__ (usually referred to as `id_token` in code samples) is a __JSON Web Token (JWT)__ that contains identity data. It is consumed by the application and used to get user information like the user's name, email, and so forth, typically used for UI display.
+
+::: panel More on tokens
+Tokens are alphanumeric strings used in token-based authentication. They allow users to authenticate with a username and password once and get a token in return which they can use from that point on. They have a limited lifetime duration.
+
+__JSON Web Tokens (JWTs)__ are tokens that conform to the [JSON Web Token Standard](https://tools.ietf.org/html/rfc7519) and contain information about an identity in the form of claims. They are self-contained in that it is not necessary for the recipient to call a server to validate the token. JWTs can be signed using a secret (with the __HMAC__ algorithm) or a public/private key pair using __RSA__. You can find more information on JWT [here](/tokens/concepts/jwts).
+
+The ID Token, which is a JWT, conforms to an industry standard (IETF [RFC 7519](https://tools.ietf.org/html/rfc7519)) and contains three parts: A header, a body and a signature.
+- The header contains the type of token and the hash algorithm used on the contents of the token.
+- The body, also called the payload, contains identity claims about a user. There are some claims with registered names, for things like the issuer of the token, the subject of the token (who the claims are about), and the time of issuance. Any number of additional claims with other names can be added, though care must be taken to keep the JWT within the browser size limitations for URLs.
+- The signature is used by the recipient of a JWT to validate the integrity of the information conveyed in the JWT.
+:::
+
+### How to validate an ID Token
+
+The validation of an ID Token requires several steps:
+1. If the ID Token is encrypted, decrypt it using the keys and algorithms that the Application specified.
+1. The Issuer Identifier for the OpenID Provider must match the value of the `iss` (issuer) claim.
+1. The `aud` (audience) claim should contain the Application's `client_id` value. The ID Token must be rejected if the ID Token does not list the Application as a valid audience, or if it contains additional audiences not trusted by the Application.
+1. If the ID Token contains multiple audiences, the Application should verify that an `azp` claim is present.
+1. If an `azp` (authorized party) claim is present, the Application should verify that its `client_id` is the claim value.
+1. The Application must validate the signature of ID Tokens according to JWS using the algorithm specified in the JWT `alg` header parameter. The Application must use the keys provided by the Issuer.
+1. The `alg` value should be the default of `RS256` or the algorithm sent by the Application in the `id_token_signed_response_alg` parameter during registration.
+1. If the JWT `alg` header parameter uses a MAC based algorithm such as `HS256`, `HS384`, or `HS512`, the octets of the UTF-8 representation of the client_secret corresponding to the `client_id` contained in the `aud` (audience) claim are used as the key to validate the signature. For MAC based algorithms, the behavior is unspecified if the `aud` is multi-valued or if an `azp` value is present that is different than the `aud` value.
+1. The current time must be before the time represented by the `exp` claim.
+1. The `iat` claim can be used to reject tokens that were issued too far away from the current time, limiting the amount of time that nonces need to be stored to prevent attacks. The acceptable range is Application specific.
+1. If a `nonce` value was sent in the Authentication Request, a `nonce` claim must be present and its value checked to verify that it is the same value as the one that was sent in the Authentication Request. The Application should check the `nonce` value for replay attacks. The precise method for detecting replay attacks is Application specific.
+1. If the `acr` claim was requested, the Application should check that the asserted claim value is appropriate.
+1. If the `auth_time` claim was requested, either through a specific request for this claim or by using the `max_age` parameter, the Application should check the `auth_time` claim value and request re-authentication if it determines too much time has elapsed since the last End-User authentication.
+
+::: note
+If you store ID Tokens on your server, you must do so securely.
+:::
+
+<%= include('./_stepnav', {
+ prev: ["Introduction", "/architecture-scenarios/web-app-sso"],
+ next: ["2. Auth0 Configuration", "/architecture-scenarios/web-app-sso/part-2"]
+}) %>
diff --git a/articles/architecture-scenarios/web-app-sso/part-2.md b/articles/architecture-scenarios/web-app-sso/part-2.md
new file mode 100644
index 0000000000..d210a4a1bb
--- /dev/null
+++ b/articles/architecture-scenarios/web-app-sso/part-2.md
@@ -0,0 +1,116 @@
+---
+description: Regular web app scenario configuration for Auth0
+toc: true
+topics:
+ - architecture
+ - regular-web-apps
+ - api-auth
+ - authorization-code
+ - lockjs
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+# Single Sign-On for Regular Web Apps: Auth0 Configuration
+
+In this section we will review all the configurations we need to apply using the [Auth0 Dashboard](${manage_url}).
+
+## Application
+
+The Auth0 configuration part starts with registering the timesheets app at the Auth0 dashboard as an __application__. An application is making protected resource requests on behalf of the resource owner (end-user).
+
+::: note
+The term "application" does not imply any particular implementation characteristics. An application can be a web app, a mobile app or an SPA. In the case of ExampleCo it is a ASP.NET Core web app.
+:::
+
+The main characteristics of an application in Auth0 are:
+- __Name__: The canonical name of the application. This is used to identify the application at the portal, emails, logs, and more.
+- __Client ID__ (read-only): The unique identifier for the application. This is the ID used in the application when setting up authentication with Auth0. It is an auto-generated alphanumeric string.
+- __Client secret__ (read-only): A string used to sign and validate tokens which will be used in the different authentication flows. It is auto-generated and it must be kept confidential.
+- __Domain__: The domain name assigned to the Auth0 account. The format of the domain is `{account-name}.auth0.com` or `{account-name}.{location}.auth0.com`, for example `ExampleCo.auth0.com`.
+- __Callback URL__: The URL where the user is redirected after they authenticate.
+
+### Create an Application
+
+ExampleCo's scenario involves only one application: the timesheets web app. Hence we have to configure one Application at Auth0 side.
+
+To register a database connection, go to the [dashboard](${manage_url}) and in the side navigation select [Applications](${manage_url}/#/applications).
+
+Click on the button __+ Create Application__. You will be prompted for the name and the type of the application. We will name our application `Timesheet-App` and select `Regular Web Applications` as the application type.
+
+
+
+When you click __Create__ you will be navigated to the [Quick Start view](${manage_url}/#/applications/${account.clientId}/quickstart). Here you can pick the technology you plan on using to build your app and the relevant how-to quickstart will be displayed.
+
+The other available views are:
+- [Settings](${manage_url}/#/applications/${account.clientId}/settings): Here you can view and update the settings of your application. This is the page you will use to retrieve information like _Domain_, _Client ID_, and _Client Secret_. In this page you will also have to [set the __Callback URL__ for your application](#configure-callback-urls).
+- [Addons](${manage_url}/#/applications/${account.clientId}/addons): Addons are plugins associated with an application in Auth0. Usually, they are third party APIs used by the application that Auth0 generates Access Tokens for (for example Salesforce, Azure Service Bus, Azure Mobile Services, SAP, and so forth). We will not use any Addons in this scenario.
+- [Connections](${manage_url}/#/applications/${account.clientId}/connections): Connections are sources of users. We will use this view shortly to enable specific connections for our application.
+
+### Configure Callback URLs
+
+The __Allowed Callback URLs__ field contains the URL(s) where Auth0 will redirect to after the user has authenticated in order for the OpenID Connect (OIDC) to complete the authentication process. You can specify multiple valid URLs by comma-separating them. You can use the star symbol as a wildcard for subdomains, for example `*.google.com`. Make sure to specify the protocol, `http://` or `https://`, otherwise the callback may fail in some cases.
+
+The Callback URL for our sample project is `http://localhost:5000/signin-auth0`. Go ahead and set this value to the __Allowed Callback URLs__ field if you plan on using our sample, otherwise add the URL you chose to deploy your application to.
+
+## Connections
+
+The next step is to configure the identity providers that will be used for authentication at the web app. Each identity provides maps to a __connection__ in Auth0. Each application needs at least one connection, and each connection can be used for more than one application.
+
+ExampleCo needs to configure two connections: one Active Directory connection for the internal employees, and one Database connection for external parties.
+
+::: panel Supported identity providers
+Auth0 supports a vast variety of protocols and identity providers:
+- Social: Allow your users to log in using Google, Facebook, LinkedIn, Github, and many more.
+- Enterprise: Allow your users to log in using Active Directory, ADFS, LDAP, SAML-P, and many more.
+- Database connections: Create your own user store by configuring a new database connection, and authenticate your users using email/username and password. The credentials can be securely stored either in the Auth0 user store, or in your own database.
+- Passwordless authentication: Allow your users to login without the need to remember a password and use an authentication channel like SMS or email.
+:::
+
+### Create a database connection
+
+To register a database connection, go to the [dashboard](${manage_url}) and in the side navigation select [Connections > Database](${manage_url}/#/connections/database).
+
+Click on the button __+ Create DB Connection__. You will be prompted for the name of the connection. We will name our connection `Timesheet-Users`.
+
+
+
+When you click __Save__ you will be navigated to the _Settings_ page for the new connection. Ensure that you enable your application to use this connection at the _Applications Using This Connection_ section.
+
+
+
+For more information on database connections refer to [Database Identity Providers](/connections/database).
+
+### Create an Active Directory / LDAP Connection
+
+Next you need to configure your Active Directory / LDAP connection. Go to the [Auth0 dashboard](${manage_url}) and in the side navigation, select [Connections > Enterprise](${manage_url}/#/connections/enterprise).
+
+There you need to create the AD / LDAP connection and install the AD Connector. You can find details in these documents:
+- [How to connect your Active Directory with Auth0](/connections/enterprise/active-directory-ldap)
+- [How to install the Active Directory/LDAP Connector](/connector)
+
+::: note
+The AD/LDAP Connector, is a bridge between your Active Directory and the Auth0 Service. This bridge is necessary because AD is typically locked down to your internal network, and Auth0 is a cloud service running on a completely different context.
+[More information](/connector/overview)
+:::
+
+Once you have configured the connection and the connector, be sure to enable your application to use this AD / LDAP connection:
+
+
+
+::: panel Kerberos support
+The AD/LDAP connector supports Kerberos to make it easer for your users to authenticate when they are on a domain-joined machine within the corporate network. To activate Kerberos on an Active Directory you have to simply enable the option in the dashboard. After enabling Kerberos you'll also be able to configure the __IP Ranges__. When users originate from these IP address ranges this information will be exposed in the SSO endpoint which means client-side SDKs like auth0.js and the Lock will be able to detect Kerberos support and allow Integrated Windows Authentication.
+[More information](/connector/kerberos)
+
+::: note
+If you enable Kerberos then you need to make some changes to the AD/LDAP's configuration file. For details refer to: [Modify the AD/LDAP Connector Settings](/connector/modify).
+:::
+
+Now that we have designed our solution and discussed the configurations needed on Auth0 side, we can proceed with integrating Auth0 with our timesheets web app. That's what the next paragraph is all about, so keep reading!
+
+<%= include('./_stepnav', {
+ prev: ["1. Solution Overview", "/architecture-scenarios/web-app-sso/part-1"],
+ next: ["3. Application Implementation", "/architecture-scenarios/web-app-sso/part-3"]
+}) %>
diff --git a/articles/architecture-scenarios/web-app-sso/part-3.md b/articles/architecture-scenarios/web-app-sso/part-3.md
new file mode 100644
index 0000000000..1f5ac0c530
--- /dev/null
+++ b/articles/architecture-scenarios/web-app-sso/part-3.md
@@ -0,0 +1,182 @@
+---
+description: Regular web app scenario application implementation
+toc: true
+topics:
+ - architecture
+ - regular-web-apps
+ - api-auth
+ - authorization-code
+ - lockjs
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+# Single Sign-On for Regular Web Apps: Application Implementation
+
+Let's walk through the implementation of our regular web application. We used ASP .NET Core for the implementation, you can find the code in [this GitHub repository](https://github.com/auth0-samples/auth0-pnp-webapp-oidc).
+
+The sample contains an application which uses Active Directory integration to authenticate company employees and an Auth0 database connection for external contractors. Authorization is implemented using rules and claims as we will see in detail in this paragraph.
+
+## User Login
+
+Auth0 provides a Lock widget which serves as a login component for your application, meaning that you do not have to implement your own login screen. The Lock widget seamlessly integrates with all of the connections you configure inside your Auth0 dashboard, whether they be database, social or enterprise connections.
+
+There are a number of different ways in which you can implement a Login screen using a web application and Auth0:
+- __Hosted Lock__: Use an instance of the Lock widget which is hosted on the Auth0 infrastructure.
+- __Embedded Lock__: Embed the Lock widget inside a web page of your application. You have some customization options for the actual Lock widget, and full control over the rest of the HTML on the page.
+- __Custom UI__: Develop a completely custom web page for the login screen. The custom HTML form will post back to your server which will in turn authenticate the user using the Authentication API. For more information on when to use a Custom UI refer to [Lock vs. a Custom UI](/libraries/when-to-use-lock).
+
+The recommended best practice is to use Hosted Lock because it is the most secure option and the easiest way to enable users to log in to your application.
+
+### Automate Home Realm Discovery (HRD)
+
+By default, Lock will display all the connections available for login. Selecting the appropriate Identity Providers from multiple options is called _Home Realm Discovery (HRD)_. In our case the options are either authenticating with Active Directory (for company employees) or using email/password for our database connection (external contractors).
+
+You may however want to avoid that first step, where the user needs to choose the Identity Provider (IdP), and have the system identify it instead of asking every time. Lock offers you the following options:
+
+- __Identify the IdP programmatically__: When you initiate an authentication transaction with Auth0 you can optionally send a `connection` parameter. This value maps directly with any connection defined in your dashboard. When using the Hosted version of Lock by calling the [`/authorize`](/api/authentication/reference#database-ad-ldap-passive-) endpoint, you can pass along a `connection` query string parameter containing the name of the connection. Alternatively, if you are using Embedded Lock, this is as simple as writing `auth0.show({connections: ['YOUR_CONNECTION']});`.
+
+ There are multiple practical ways of getting the `connection` value. One of them is to use __vanity URLs__: for example, company employees will use `https://internal.yoursite.com`, while external contractors will use `https://external.yoursite.com`.
+
+- __Use email domains__: Lock can use email domains as a way of routing authentication requests. Enterprise connections in Auth0 can be mapped to `domains`. If a connection has this setup, then the password textbox gets disabled automatically when typing an email with a mapped domain. Note that you can associate multiple domains to a single connection.
+
+For additional information on this topic refer to: [Selecting the connection in Auth0 for multiple login options](/libraries/lock/v10/selecting-the-connection-for-multiple-logins).
+
+## Session Management
+
+When talking about managing sessions, there are typically three layers of sessions we need to consider:
+
+- __Application Session__: The first is the session inside the application. Even though your application uses Auth0 to authenticate users, you will still need to keep track of the fact that the user has logged in to your application. In a normal web application this is achieved by storing information inside a cookie.
+- __Auth0 session__: Next, Auth0 will also keep a session and store the user's information inside a cookie. Next time when a user is redirected to the Auth0 Lock screen, the user's information will be remembered.
+- __Identity Provider session__: The last layer is the Identity Provider, for example Facebook or Google. When you allow users to sign in with any of these providers, and they are already signed into the provider, they will not be prompted to sign in. They may simply be required to give permissions to share their information with Auth0 and in turn your application.
+
+When developing a web application, you will therefore need to keep track of the fact that the user has logged in to your Web application. You can do this by making use of a cookie-based session to keep track of the fact that the user has signed in, and also store any of the user related information or tokens.
+
+::: panel How do I control the duration of the user's local application session? Can I drive that from Auth0?
+The web app has full control over the user's local application session. How this is done usually depends on the web stack being used (for example, ASP.NET). Regardless, all approaches ultimately use one or more cookies to control the session. The developer can choose to use the expiration of the JWT ID Token returned by Auth0 to control their session duration or ignore it completely. Some developers store the ID Token itself in session state and end the user's session when it has expired.
+
+The reason why you would use the expiration of the token to determine the expiration of the local session is because it gives you centralized control of the duration of a user session from the Auth0 Dashboard.
+:::
+
+The login flow is as follows:
+
+
+
+1. __Initiate OIDC Authentication Flow__: The user's browser will send a request to Auth0 to initiate the OIDC flow.
+1. __Set SSO Cookie__: Auth0 will set a cookie to store the user's information.
+1. __Code exchange and return ID Token__: Auth0 will make a request back to the web server and return the code. The web server will exchange the code for an ID Token.
+1. __Set auth cookie and send response__: The web server will send a response back to the browser and set the application authentication cookie to store the user's session information.
+1. __Auth cookie sent with every subsequent request__: The application authentication cookie will be sent on every subsequent request as proof that the user is authenticated.
+
+::: panel How does Auth0's SSO session impact the application's session?
+Auth0 manages its own single-sign-on session. Applications can choose to honor or ignore that SSO session when it comes to maintaining their own local session. The Lock widget even has a special feature where it can detect if an Auth0 SSO session exists and ask the user if they wish to log in again as that same user.
+
+
+
+If they do so, they are signed in without having to re-enter their credentials with the actual IDP. Even though the user didn't authenticate, the application still performs an authentication flow with Auth0 and obtains a new ID Token, which can be used to then manage the new local application session.
+:::
+
+**See the implementation in [ASP.NET Core](/architecture-scenarios/application/web-app-sso/implementation-aspnetcore#configure-the-cookie-and-oidc-middleware)**.
+
+## User Logout
+
+When logging the user out, you will once again need to think about the three layers of sessions which we spoke about before:
+- __Application Session__: You need to log out the user from your Web Application, by clearing their session.
+- __Auth0 session__: You need to log out the user from Auth0. To do this you redirect the user to `https://${account.namespace}/v2/logout`. Redirecting the user to this URL clears all single sign-on cookies set by Auth0 for the user.
+- __Identity Provider session__: Although this is not common practice, you can force the user to log out from the Identity Provider used, for example Facebook or Google. To do this add a `federated` query string parameter to the logout URL: `https://${account.namespace}/v2/logout?federated`.
+
+To redirect a user after logout, add a `returnTo` query string parameter with the target URL as the value: `https://${account.namespace}/v2/logout?returnTo=http://www.example.com`. Note, that you will need to add the `returnTo` URL as an __Allowed Logout URLs__. For more information on how to implement this refer to: [Logout](/logout).
+
+The logout flow (not including federated logout) is as follows:
+
+
+
+1. __Initiate Logout Flow__: The logout flow will be initiated from the browser, for example by the user clicking a _Logout_ link. A request will be made to the web server.
+1. __Clear user’s local session__: The user's Application Session / Cookie will be cleared.
+1. __Redirect browser to Auth0 Logout__: The user's browser will be redirected to the Auth0 Logout URL.
+1. __Clear SSO Cookie__: Auth0 will clear the user's SSO Cookie.
+1. __Redirect to post-logout URL__: Auth0 will return a redirect response and redirect the user's browser to the `returnTo` query string parameter.
+
+**See the implementation in [ASP.NET Core](/architecture-scenarios/application/web-app-sso/implementation-aspnetcore#implement-the-logout)**.
+
+## Access Control
+
+Authorization refers to the process of determining what actions a user can perform inside your application.
+
+You can either implement authorization directly inside your application, independently of Auth0, or use one of the available ways to retrieve the user authorization levels, put them as authorization claims inside the ID Token and validate these claims inside your application, once you retrieve the token, to control access.
+
+There are various ways in which you can retrieve and set the user authorization claims when using Auth0:
+- By configuring and using the [Auth0 Authorization Extension](/extensions/authorization-extension).
+- By using Active Directory groups. These can be used in combination with the Authorization Extension by mapping Active Directory Groups to Groups you define using the Authorization extension.
+- Add metadata to the user's profile by making use of [rules](/rules#add-roles-to-a-user).
+- By calling an external services from inside a [rule](/rules).
+
+Since in our case the company has already Active Directory set up, we will enforce access control using the Authorization Extension in combination with Active Directory groups.
+
+::: panel Authorization Extension
+At this point in time the authorization extension is primarily designed to enforce coarse-grained authorization, for example to control access to an application based on a user's group membership. It is not necessarily designed to control fine-grained access (such as whether a user can perform a specific action inside the application), even though this is how we are utilizing it in this instance.
+:::
+
+All users will implicitly be regular users, but timesheet administrators will be assigned to an `Admin` group which will allow them to approve timesheets. The Authorization Extension allows for mapping groups to existing group membership.
+
+All timesheet administrators will be assigned to the `Timesheet Administrators` group on Active Directory, which will be automatically mapped to the `Admin` group inside the Timesheet Application.
+
+When you install the Authorization Extension, it creates a rule in the background, which does the following:
+1. Determine the user's group membership.
+1. Store the user's group membership info as part of the `app_metadata`.
+1. Add the user's group membership to the outgoing token.
+1. Verify that the user has been granted access to the current application.
+
+
+### Install the Authorization Extension
+
+To install the Authorization extension navigate to the [Extensions](${manage_url}/#/extensions) view of your Auth0 Dashboard, and select and install the Auth0 Authorization extension.
+
+
+
+Once installed, you will see the app listed under _Installed Extensions_.
+
+When you click on the link to open the extension for the first time, you will be prompted to provide permission for the extension to access your Auth0 account. If you do so, you will be redirected to the Authorization Dashboard.
+
+Once on the Authorization Dashboard, navigate to Groups in the navigation menu, and create a new group called `Admin`.
+
+
+
+After the group has been added you can click on the new group to go to the group management section. Go to the _Group Mappings_ tab and add a new group mapping which will map all Active Directory users in the `Timesheet Admins` groups to the `Admin` group you just created.
+
+
+
+Once you click __Save__ you can see the new mapping listed.
+
+
+
+With the mapping configured you only need to maintain membership to the `Timesheet Admins` group in Active Directory, and those users will be automatically mapped to the `Admin` group inside our application.
+
+For more information refer to the [Authorization Extension documentation](/extensions/authorization-extension).
+
+### Enforce permissions in your application
+
+When you installed the Authorization Extension, it also created an Auth0 rule which will add an `authorization` claim with all the authorization related settings for a particular user. The groups for a user will be added as a sub-claim of the `authorization` claim called `groups` and all the groups a user belongs to will be added as an array to this claim. This is an example of what JSON payload of a ID Token may look like with the groups listed:
+
+```json
+{
+ "sub": "1234567890",
+ "name": "John Doe",
+ "authorization": {
+ "groups": ["Admin"]
+ }
+}
+```
+
+In your application you will therefore need to decode the ID Token returned when a user is authenticated, and extract the groups which a user belongs to from the `authorization` claim. You can then store these groups, along with other user information inside the user's session, and subsequently query these to determine whether a user has permissions to perform a certain action based on their group membership.
+
+::: note
+See the implementation in [ASP.NET Core](/architecture-scenarios/application/web-app-sso/implementation-aspnetcore#implement-admin-permissions).
+:::
+
+<%= include('./_stepnav', {
+ prev: ["2. Auth0 Configuration", "/architecture-scenarios/web-app-sso/part-2"],
+ next: ["4. Conclusion", "/architecture-scenarios/web-app-sso/part-4"]
+}) %>
diff --git a/articles/architecture-scenarios/web-app-sso/part-4.md b/articles/architecture-scenarios/web-app-sso/part-4.md
new file mode 100644
index 0000000000..d213436539
--- /dev/null
+++ b/articles/architecture-scenarios/web-app-sso/part-4.md
@@ -0,0 +1,26 @@
+---
+description: Regular web app scenario conclusion
+toc: true
+topics:
+ - architecture
+ - regular-web-apps
+ - api-auth
+ - authorization-code
+ - lockjs
+contentType: tutorial
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+# Single Sign-On for Regular Web Apps: Conclusion
+
+In this tutorial we covered a simple scenario: a regular web app, hosted in the cloud, using Auth0 for authentication, while utilizing the existing Active Directory user store. We learned what OpenID Connect (OIDC) offers and why it was preferable for this business case, how the Authentication Flow works, what an ID Token is and how to validate and manipulate it, how to configure applications and connections on Auth0 dashboard, how to implement user login and logout using Lock, and how session management and access control works.
+
+We started by describing the business case and the requirements and went on explaining how each requirement can be met and the thought process behind each choice that was made.
+
+We used ASP .NET Core for the sample web app implementation, hopefully though after going through this document you are able to build such a web app using the framework you prefer.
+
+<%= include('./_stepnav', {
+ prev: ["3. Application Implementation", "/architecture-scenarios/web-app-sso/part-3"]
+}) %>
diff --git a/articles/architecture-scenarios/web-saml.md b/articles/architecture-scenarios/web-saml.md
new file mode 100644
index 0000000000..6f53f1d7d1
--- /dev/null
+++ b/articles/architecture-scenarios/web-saml.md
@@ -0,0 +1,42 @@
+---
+order: 05
+title: Regular Web App (using SAML)
+image: /media/articles/architecture-scenarios/web-saml.png
+extract: Traditional web application which needs to authenticate users using SAML2
+description: Learn about an architecture scenario that involves using a traditional web application to authenticate users using SAML2.
+beta: true
+topics:
+ - architecture
+ - regular-web-apps
+ - api-auth
+ - lockjs
+ - saml
+contentType: concept
+useCase:
+ - invoke-api
+ - secure-an-api
+ - build-an-app
+---
+
+# Regular Web App (using SAML)
+
+::: note
+This architecture scenario is under construction.
+:::
+
+
+
+In this scenario, you have a traditional web application that needs to authenticate users using SAML2. After a user has successfully authenticated using the SAML flow, the Authorization Server POSTs the SAML Response (which contains SAML Assertions about the user) to a server-side endpoint (aka callback) in your application. Therefore, your application needs a SAML library that can process that response, validate the user, and create a local login session, which is usually stored using one or more cookies.
+
+::: note
+In this scenario, an Access Token is also returned, but it is rarely used because no API exists against which the user needs to be authenticated.
+:::
+
+::: warning
+If you are using Auth0 as a SAML Identity Provider (IdP) and are processing SAML responses in your own code, you will need to verify whether the libraries you use are vulnerable to SAML exploits.
+:::
+
+## Read More
+
+* Learn how to implement login for this scenario using [Universal Login](/universal-login) or [Lock](/libraries/lock)
+* Learn about [SAML](/saml-configuration)
diff --git a/articles/authorization/_includes/_enable-authz-core.md b/articles/authorization/_includes/_enable-authz-core.md
new file mode 100644
index 0000000000..bbff4048bd
--- /dev/null
+++ b/articles/authorization/_includes/_enable-authz-core.md
@@ -0,0 +1,6 @@
+
+::: warning
+For [role-based access control (RBAC)](/authorization/concepts/rbac) to work properly, you must enable it for your API using either the [Dashboard](/dashboard/guides/apis/enable-rbac) or the [Management API](/api/management/guides/apis/enable-rbac).
+
+Authorization Core functionality is different from the Authorization Extension. For a comparison between the two products, see [Authorization Core vs. Authorization Extension](/authorization/concepts/core-vs-extension).
+:::
\ No newline at end of file
diff --git a/articles/authorization/_includes/_predefine-permissions.md b/articles/authorization/_includes/_predefine-permissions.md
new file mode 100644
index 0000000000..0f2726b6f5
--- /dev/null
+++ b/articles/authorization/_includes/_predefine-permissions.md
@@ -0,0 +1,3 @@
+::: note
+Permissions are selected from pre-defined values. If your list of permissions is blank, you need to make sure you have [defined permissions for your API](/dashboard/guides/apis/add-permissions-apis). You also need to have already [created an API](/getting-started/set-up-api) in your Auth0 Dashboard.
+:::
\ No newline at end of file
diff --git a/articles/authorization/_includes/_predefine-roles.md b/articles/authorization/_includes/_predefine-roles.md
new file mode 100644
index 0000000000..ec55ac3b99
--- /dev/null
+++ b/articles/authorization/_includes/_predefine-roles.md
@@ -0,0 +1,3 @@
+::: note
+Roles are selected from pre-defined values. If your list of roles is blank, you need to make sure you have [created roles](/dashboard/guides/roles/create-roles).
+:::
\ No newline at end of file
diff --git a/articles/authorization/concepts/authz-and-authn.md b/articles/authorization/concepts/authz-and-authn.md
new file mode 100644
index 0000000000..9290845ab3
--- /dev/null
+++ b/articles/authorization/concepts/authz-and-authn.md
@@ -0,0 +1,33 @@
+---
+description: Explore the differences between authentication and authorization.
+toc: true
+topics:
+ - authorization
+ - authentication
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Authentication and Authorization
+
+While often used interchangeably, [authentication](/application-auth/current) and [authorization](/authorization) represent fundamentally different functions. In this article, we compare and contrast the two to show how they protect applications in complementary ways.
+
+In simple terms, authentication is the process of verifying who a user is, while authorization is the process of verifying what they have access to.
+
+Comparing these processes to a real-world example, when you go through security in an airport, you show your ID to authenticate your identity. Then, when you arrive at the gate, you present your boarding pass to the flight attendant, so they can authorize you to board your flight and allow access to the plane.
+
+Here's a quick overview of the differences between authentication and authorization:
+
+| **Authentication** | **Authorization** |
+|--------------------|-------------------|
+| Determines whether users are who they claim to be | Determines what users can and cannot access |
+| Challenges the user to validate credentials (for example, through passwords, answers to security questions, or facial recognition) | Verifies whether access is allowed through policies and rules |
+| Usually done before authorization | Usually done after successful authentication |
+| Generally, transmits info through an ID Token | Generally, transmits info through an Access Token |
+| Generally governed by the OpenID Connect (OIDC) protocol | Generally governed by the OAuth 2.0 framework |
+| Example: Employees in a company are required to authenticate through the network before accessing their company email | Example: After an employee successfully authenticates, the system determines what information the employees are allowed to access |
+
+In short, access to a resource is protected by both authentication and authorization. If you can't prove your identity, you won't be allowed into a resource. And even if you can prove your identity, if you are not authorized for that resource, you will still be denied access.
diff --git a/articles/authorization/concepts/authz-rules.md b/articles/authorization/concepts/authz-rules.md
new file mode 100644
index 0000000000..8a69741e18
--- /dev/null
+++ b/articles/authorization/concepts/authz-rules.md
@@ -0,0 +1,43 @@
+---
+description: Understand how rules apply to authorization policies and Auth0's role-based access system (RBAC).
+toc: true
+topics:
+ - authorization
+ - rbac
+ - roles
+ - permissions
+ - policies
+ - rules
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Rules for Authorization Policies
+
+You can append [Rules](/rules) to the pre-configured authorization policy to exercise additional control over permitting or denying user access. A rule contains custom code that makes an authorization decision based on appropriate logic. When combined with other rules, it helps define what happens in different contexts.
+
+Rules can restrict access based on any combination of attributes you store for users, such as user department, time of day, location, or any other user or API attribute (like username, security clearance, or API name).
+
+For example, if you were using rules to provide finely-grained access control at a non-profit organization, you could give only W2 employees working in the Research and Development department in the New Delhi office access to an application.
+
+For samples of rule implementations with authorization policies, see [Sample Use Cases: Rules with Authorization](/authorization/concepts/sample-use-cases-rules).
+
+## Rules in the authorization process
+
+Based on the order in which they run, rules can change the outcome of the authorization decision prior to the permissions being added to the Access Token. The basic process with rules injected is as follows:
+
+1. The user tries to authenticate with the application.
+2. Auth0 brings the request to the selected identity provider.
+3. Once the identity provider confirms that user credentials are valid, all created rules run in the order in which they are configured in the Dashboard.
+4. Assuming no rule has restricted the user's access, the user is authorized to access the application.
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Authorization Policies](/authorization/concepts/policies)
+- [Sample Use Cases: Rules with Authorization](/authorization/concepts/sample-use-cases-rules)
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
\ No newline at end of file
diff --git a/articles/authorization/concepts/core-vs-extension.md b/articles/authorization/concepts/core-vs-extension.md
new file mode 100644
index 0000000000..854e27f7ea
--- /dev/null
+++ b/articles/authorization/concepts/core-vs-extension.md
@@ -0,0 +1,92 @@
+---
+description: Understand the differences between Auth0's core RBAC release and the Authorization Extension.
+toc: true
+topics:
+ - authorization
+ - authorization-extension
+ - rbac
+ - roles
+ - permissions
+ - policies
+ - rules
+ - extensions
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Authorization Core vs. Authorization Extension
+
+Auth0 currently provides two ways of implementing [role-based access control (RBAC)](/authorization/concepts/rbac): our Core implementation, which is currently being released, and our Authorization Extension, which will eventually be deprecated. Our Core implementation improves performance and scalability and will eventually provide a more flexible RBAC system than the Authorization Extension.
+
+While we recommend using the RBAC features present in the Authorization Core, we recognize that some implementations may require use of the Authorization Extension until Authorization Core features match its full functionality. To help you decide which feature is right for your implementation, we present the differences between the two:
+
+| Feature | Authorization Core | Authorization Extension |
+|---------|-------------------------|------------------------------|
+| **Roles** |
+| Create/edit/delete roles | Yes | Yes |
+| Search roles by name | In future release | Yes |
+| Roles can contain permissions from one or more APIs | Yes | No |
+| Roles can be assigned to groups | In future release | Yes |
+| Roles are attached to specific applications | No | Yes |
+| Roles can contain permissions from any application | Yes | No |
+| Roles can be nested and are hierarchical | In future release | No |
+| Roles can be assigned across multiple tenants | To be determined | No |
+| View permissions by role | Yes | Yes |
+| View users by role | Yes | Yes |
+| **Users** |
+| Create/edit/delete users | Yes | Yes |
+| Search users by user, email, connection | Yes | Yes |
+| Search users by identity provider, login count, last login, phone number | Yes | No |
+| Search users using lucene syntax | Yes | No |
+| Users can be assigned to roles | Yes - up to 50 roles per user | Yes |
+| Users can be assigned to groups | In future release | Yes |
+| View roles by user | Yes | Yes |
+| View permissions by user | Yes | Yes |
+| Automatic sync between user permissions and user profile | In future release | No |
+| **Permissions** |
+| Create/edit/delete permissions | Yes | Yes |
+| Search permissions by name, description | In future release | Yes |
+| Permissions can be assigned directly to users | Yes | No |
+| Permissions can be assigned directly to roles | Yes | Yes |
+| Permissions are attached to applications | No | Yes |
+| Permissions are attached to APIs | Yes | No |
+| View users by permission | In future release | No |
+| View roles by permission | In future release | No |
+| **Groups** |
+| Create/edit/delete groups | In future release | Yes |
+| Search groups by name | In future release | Yes |
+| Groups can be sourced from local users | In future release | Yes |
+| Groups can be sources from third-party directories (for example, AD, LDAP, SAML) | In future release | No |
+| Groups can be nested and are hierarchical | In future release | Yes |
+| Groups can be mapped from pre-existing groups and connections | In future release | Yes |
+| Groups can contain roles from any application | In future release | Yes |
+| View nested groups by group | In future release | Yes |
+| View roles by group | In future release | Yes |
+| View users by group | In future release | Yes |
+| **Configuration** |
+| Customize configuration | Yes | Yes |
+| Rules allow for customization of authorization decision | Yes | Yes |
+| Configure whether to allow API access to authorization context | Yes | Yes |
+| Configure adding permissions to Access Token | Yes | Yes |
+| Configure adding groups or roles to Access Token | To be determined | Yes |
+| Configure whether authorization context persists in user's app_metadata | To be determined | Yes |
+| Configure third-party identity provider pass-through for groups, roles, and permissions | To be determined | Yes |
+| User import/export via JSON | To be determined | Yes |
+| Create custom authorization policies | Yes | No |
+| Create deny assignments | To be determined | No |
+| **Performance/Scalability** |
+| Enhanced performance and scalability | Yes - See [Authorization Core RBAC Limits](/authorization/reference/rbac-limits) | No - Limited to 500KB of data (1000 groups, 3000 users, where each user is a member of 3 groups; or 20 groups, 7000 users, where each user is a member of 3 groups) |
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Authorization Core RBAC Limits](/authorization/reference/rbac-limits)
+- [Authorization Policies](/authorization/concepts/policies)
+- [Rules for Authorization Policies](/authorization/concepts/authz-rules)
+- [Sample Use Cases: Role-Based Access Control](/authorization/concepts/sample-use-cases-rbac)
+- [Sample Use Cases: Rules with Authorization](/authorization/concepts/sample-use-cases-rules)
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
+- [Authorization Extension](/extensions/authorization-extension)
\ No newline at end of file
diff --git a/articles/authorization/concepts/policies.md b/articles/authorization/concepts/policies.md
new file mode 100644
index 0000000000..d7bb142d50
--- /dev/null
+++ b/articles/authorization/concepts/policies.md
@@ -0,0 +1,39 @@
+---
+description: Understand the concept of authorization policies and how they apply in Auth0.
+toc: true
+topics:
+ - authorization
+ - rbac
+ - roles
+ - permissions
+ - policies
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Authorization Policies
+
+Behind the scenes, [role-based authorization](/authorization/concepts/rbac) uses a pre-configured authorization policy, which contains conditions that allow code to evaluate whether a user should be permitted to access a protected API.
+
+The authorization policy determines:
+
+* how to define and organize the users or roles that are affected by the policy
+* what logic and conditions apply to the policy and whether their outcome permits or denies access
+
+When using Auth0's core authorization and [role-based access control (RBAC)](/authorization/concepts/rbac), the policy includes evaluating the roles and permissions assigned to users. To use these features, you must [enable role-based access control for APIs](/dashboard/guides/apis/enable-rbac).
+
+You can further customize the authorization policy by using [rules](/rules). To learn how, see [Rules for Authorization Policies](/authorization/concepts/authz-rules).
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Rules for Authorization Policies](/authorization/concepts/authz-rules)
+- [Sample Use Cases: Role-Based Access Control](/authorization/concepts/sample-use-cases-rbac)
+- [Sample Use Cases: Rules with Authorization](/authorization/concepts/sample-use-cases-rules)
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
+
+
diff --git a/articles/authorization/concepts/rbac.md b/articles/authorization/concepts/rbac.md
new file mode 100644
index 0000000000..a6821eb8c7
--- /dev/null
+++ b/articles/authorization/concepts/rbac.md
@@ -0,0 +1,66 @@
+---
+description: Understand the concept of role-based access control and how it applies in Auth0.
+toc: true
+topics:
+ - authorization
+ - rbac
+ - roles
+ - permissions
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Role-Based Access Control
+
+Role-based access control (RBAC) refers to the idea of assigning permissions to users based on their role within an organization. It provides fine-grained control and offers a simple, manageable approach to access management that is less prone to error than assigning permissions to users individually.
+
+When using RBAC, you analyze the system needs of your users and group them into roles based on common responsibilities and needs. You then assign one or more roles to each user and one or more permissions to each role. The user-role and role-permissions relationships make it simple to perform user assignments since users no longer need to be managed individually, but instead have privileges that conform to the permissions assigned to their role(s).
+
+For example, if you were applying RBAC at a non-profit organization, you could give all W2 employees access to Google for research, and all contractors access to corporate email.
+
+When planning your access control strategy, it's best practice to assign users the fewest number of permissions that allow them to get their work done.
+
+## Benefits of RBAC
+
+With RBAC, access management is easier as long as you adhere strictly to the role requirements. RBAC helps you:
+
+* create systematic, repeatable assignment of permissions
+* easily audit user privileges and correct identified issues
+* quickly add and change roles, as well as implement them across APIs
+* cut down on the potential for error when assigning user permissions
+* integrate third-party users by giving them pre-defined roles
+* more effectively comply with regulatory and statutory requirements for confidentiality and privacy
+
+## RBAC Model
+
+### Roles
+
+Essentially, a role is a collection of permissions that you can apply to users. Using roles makes it easier to add, remove, and adjust permissions than assigning permissions to users individually. As your user base increases in scale and complexity, roles become particularly useful.
+
+You can also use roles to collect permissions defined for various APIs. For example, say you have a marketing module that allows users to create and distribute newsletters to customers. Your marketing content specialist creates all of the newsletters and prepares them for distribution. Similarly, you have an event module that allows users to create, publish, and manage event registration. Your event coordinator creates the events. Once the VP of Marketing approves the newsletters and events, their assistant publishes the events and distributes the newsletters. In this case, your Newsletter API could have a `distribute:newsletters` permission and your Event API could have a `publish:events` permission. These permissions could then be gathered into a role called `Marketing Publisher` and assigned to the VP of Marketing's assistant.
+
+## Overlapping role assignments
+
+RBAC is an additive model, so if you have overlapping role assignments, your effective permissions are the union of your role assignments.
+
+For example, let's say you have an API that provides data for an event application. You create a role of `Organizer` and assign it permissions that allow it to view, create, and edit events. You also create a role of `Registrant` and assign it permissions that allow it to view and register for events. Any users with both `Organizer` and `Registrant` roles will be able to view, create, edit, and register for events.
+
+## Role-based access control in Auth0
+
+<%= include('../../_includes/_rbac_methods') %>
+
+### Extending RBAC
+
+You can provide even more finely-grained control by using [rules](/rules) to restrict access based on a combination of attributes, such as user department, time of day, location of access, or any other user or API attribute (for example, username, security clearance, or API name).
+
+For more info about using rules with authorization policies, see [Rules with Authorization Policies](/authorization/concepts/authz-rules).
+
+## Keep reading
+
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
+- [Enable Role-Based Access Control (RBAC) for APIs](/dashboard/guides/apis/enable-rbac)
+- [Authorization Core vs. Authorization Extension](/authorization/concepts/core-vs-extension)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
diff --git a/articles/authorization/concepts/sample-use-cases-rbac.md b/articles/authorization/concepts/sample-use-cases-rbac.md
new file mode 100644
index 0000000000..4274288d20
--- /dev/null
+++ b/articles/authorization/concepts/sample-use-cases-rbac.md
@@ -0,0 +1,60 @@
+---
+description: Learn how to implement roles-based authorization (RBAC) in different scenarios and explore how to use rules with RBAC.
+toc: true
+topics:
+ - authorization
+ - authorization-extension
+ - rbac
+ - roles
+ - permissions
+ - policies
+ - rules
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Sample Use Cases: Role-Based Access Control
+
+Let's take a look at an example of why you might need and how you could use [role-based access control (RBAC)](/authorization/concepts/rbac) in your authorization flow.
+
+Let's say you are a business who provides business-to-business software-as-a-service to non-profit organizations. Your product allows non-profits to create, manage, and market products to potential donors. Your application contains several different modules, two of which are:
+
+* a gift shop point of sale (POS) module that enables non-profits to effectively create pop-up t-shirt shops and manage their sales.
+* a marketing module that allows non-profits to create and distribute newsletters to their donors.
+
+You want to use Auth0 to control the access of your non-profit customers to different parts of your application. Without RBAC, all non-profit employees and volunteers will have access to all features of your application, which is not ideal, especially since one of them is an animal rescue who has a variety of volunteers with knowledge of only the area in which they volunteer.
+
+Instead, you implement RBAC, [creating some permissions](/dashboard/guides/apis/add-permissions-apis) that users of your gift shop POS module would need:
+
+* `read:catalog-item`
+* `read:customer-profile`
+* `create:invoice`
+
+And to make these easier to manage, you [create a role](/dashboard/guides/roles/create-roles) called `Gift Shop Manager` and [add these permissions to that role](/dashboard/guides/roles/add-permissions-roles).
+
+Similarly, you [create permissions](/dashboard/guides/apis/add-permissions-apis) for users of your marketing module, which include:
+
+* `create:newsletter`
+* `edit:newsletter`
+* `delete:newsletter`
+* `send:newsletter`
+* `edit:distribution-list`
+
+And you [create a role](/dashboard/guides/roles/create-roles) called `Newsletter Admin` and [add these permissions to that role](/dashboard/guides/roles/add-permissions-roles).
+
+Now, when your animal rescue brings in their volunteer, Astrid, to run their pop-up t-shirt shop, Astrid can be [assigned the role](/dashboard/guides/users/assign-roles-users) of `Gift Shop Manager`. When you assign this role to Astrid, she is granted all the permissions that you assigned to the role. Since Astrid knows nothing about publishing newsletters (and isn't the best with email), you never assigned her the `Newsletter Admin` role, so she never has access to the marketing module.
+
+From a more technical perspective, when Astrid logs into your product, Auth0 authenticates and authorizes her and includes the permissions in the returned Access Token. Then, your product inspects the token to learn which module to display to Astrid.
+
+By using Auth0's RBAC, you avoid building and maintaining separate authorization systems; instead, you use the token you already receive during authorization. And when Astrid moves away or decides she is tired of running the gift shop and would rather coordinate the foster program, you can easily [remove the `Gift Shop Manager` role](/dashboard/guides/users/remove-user-roles) from her and [assign her a new role](/dashboard/guides/users/assign-roles-users).
+
+And if maintaining the roles and permissions for all of your customers becomes too unwieldy, you can also use the Auth0 API to create a module within your product that allows customers to manage their own RBAC, thereby reducing liability and cutting staffing costs.
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
\ No newline at end of file
diff --git a/articles/authorization/concepts/sample-use-cases-rules.md b/articles/authorization/concepts/sample-use-cases-rules.md
new file mode 100644
index 0000000000..b8c23f78bb
--- /dev/null
+++ b/articles/authorization/concepts/sample-use-cases-rules.md
@@ -0,0 +1,119 @@
+---
+description: Learn how to use rules with roles-based access control (RBAC). For use with our Authorization Core feature set.
+toc: true
+topics:
+ - authorization
+ - authorization-extension
+ - rbac
+ - roles
+ - permissions
+ - policies
+ - rules
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Sample Use Cases: Rules with Authorization
+
+With [rules](/rules), you can modify or complement the outcome of the decision made by the pre-configured [authorization policy](/authorization/concepts/policies) to handle more complicated cases than is possible with [role-based access control (RBAC)](/authorization/concepts/rbac) alone. Based on the order in which they run, rules can change the outcome of the authorization decision prior to the permissions being added to the Access Token. They can also allow you to customize the content of your tokens.
+
+## Allow access only on weekdays for a specific application
+
+Let's say you have an application that you want to make sure is only accessible during weekdays. To do this, you would [create the following rule](/dashboard/guides/rules/create-rules):
+
+```js
+function (user, context, callback) {
+
+ if (context.clientName === 'APP_NAME') {
+ const d = Date.getDay();
+
+ if (d === 0 || d === 6) {
+ return callback(new UnauthorizedError('This app is only available during the week.'));
+ }
+ }
+
+ callback(null, user, context);
+}
+```
+
+If a user attempts to access the application during the weekend, access will be denied, even if they authenticate and have the appropriate privileges.
+
+## Allow access only to users who are inside the corporate network
+
+Let's say you want to allow access to an application, but only for users who are accessing the application from inside your corporate network. To do this, you would [create the following rule](/dashboard/guides/rules/create-rules):
+
+```js
+function (user, context, callback) {
+ const ipaddr = require('ipaddr.js');
+ const corp_network = "192.168.1.134/26";
+ const current_ip = ipaddr.parse(context.request.ip);
+
+ if (!current_ip.match(ipaddr.parseCIDR(corp_network))) {
+ return callback(new UnauthorizedError('This app is only available from inside the corporate network.'));
+ };
+
+ callback(null, user, context);
+}
+```
+
+If the user is outside the corporate network, they will be denied access even if they successfully authenticate and have the appropriate privileges.
+
+## Add user roles to tokens
+
+If you [enable RBAC for APIs](/dashboard/guides/apis/enable-rbac) along with "Add Permissions in the Access Token" (or [enable RBAC via the Management API](/api/management/guides/apis/enable-rbac) and set the **Token Dialect** to `access_token_authz`), you will receive user permissions in your Access Tokens. To add user roles to tokens, you would use the `context.authorization` object when you [create the following rule](/dashboard/guides/rules/create-rules):
+
+```js
+function (user, context, callback) {
+ const namespace = 'http://demozero.net';
+ const assignedRoles = (context.authorization || {}).roles;
+
+ let idTokenClaims = context.idToken || {};
+ let accessTokenClaims = context.accessToken || {};
+
+ idTokenClaims[`<%= "${namespace}" %>/roles`] = assignedRoles;
+ accessTokenClaims[`<%= "${namespace}" %>/roles`] = assignedRoles;
+
+ context.idToken = idTokenClaims;
+ context.accessToken = accessTokenClaims;
+
+ callback(null, user, context);
+}
+
+```
+
+## Manage Delegated Administration Extension roles using the Authorization Core feature set
+
+Although the [Delegated Administration Extension (DAE)](/extensions/delegated-admin) and the Authorization Core feature set are completely separate features, you can use the Authorization Core feature set to create and manage roles for the DAE if you use a rule.
+
+1. [Create DAE roles](/dashboard/guides/roles/create-roles) using the Authorization Core feature set.
+
+The names of the roles you create must match the names of the [pre-defined DAE roles](/extensions/delegated-admin#assign-roles-to-users).
+
+2. [Assign the DAE roles you created to the appropriate users](/dashboard/guides/users/assign-roles-users) using the Authorization core feature set.
+
+3. Add user roles to the DAE namespace in the ID Token. To do so, [create the following rule](/dashboard/guides/rules/create-rules), remembering to replace the `CLIENT_ID` placeholder value with your application's Client ID:
+
+```js
+function (user, context, callback) {
+ if (context.clientID === 'CLIENT_ID') {
+ const namespace = 'https://example.com/auth0-delegated-admin';
+ context.idToken[namespace] = {
+ roles: (context.authorization || {}).roles
+ };
+ }
+ callback(null, user, context);
+}
+```
+
+::: note
+Your claim should be [namespaced](/tokens/guides/create-namespaced-custom-claims).
+:::
+
+## Keep reading
+
+- [Rules for Authorization Policies](/authorization/concepts/authz-rules)
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
diff --git a/articles/authorization/concepts/troubleshooting.md b/articles/authorization/concepts/troubleshooting.md
new file mode 100644
index 0000000000..cc3d0d2c60
--- /dev/null
+++ b/articles/authorization/concepts/troubleshooting.md
@@ -0,0 +1,28 @@
+---
+description: Explore solutions to common issues experienced when implementing role-based access control (RBAC) using the Authorization Core feature set.
+topics:
+ - authorization
+ - rbac
+ - roles
+ - permissions
+ - policies
+ - troubleshooting
+contentType:
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Troubleshoot Role-Based Access Control and Authorization
+
+Here are some solutions to common issues experienced when implementing [role-based access control (RBAC)](/authorization/concepts/rbac) using the Authorization Core feature set.
+
+## Role-based access control is enabled for my API, but the scopes claim is not showing what [you say it should](/dashboard/guides/apis/enable-rbac).
+
+Make sure that you aren't setting `accessToken.scope` in a [rule]. Remember that any configured [authorization rules](/authorization/concepts/authz-rules) run _after_ the RBAC-based authorization decisions are made, so they may override default behavior.
+
+## Keep reading
+
+- [Sample Use Cases: Role-Based Access Control](/authorization/concepts/sample-use-cases-rbac)
+- [Sample Use Cases: Rules with Authorization](/authorization/concepts/sample-use-cases-rules)
\ No newline at end of file
diff --git a/articles/authorization/guides/how-to.md b/articles/authorization/guides/how-to.md
new file mode 100644
index 0000000000..1d92b49edc
--- /dev/null
+++ b/articles/authorization/guides/how-to.md
@@ -0,0 +1,35 @@
+---
+description: Learn to use Auth0's API Authorization features using the Management Dashboard.
+topics:
+ - authorization
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# How to Use Auth0's Core Authorization Feature Set
+
+The core Authorization features of Auth0 allow for [role-based access control (RBAC)](/authorization/concepts/rbac) of your APIs.
+
+<%= include('../../_includes/_rbac_vs_extensions') %>
+
+<%= include('../_includes/_enable-authz-core') %>
+
+To use the core functionality most efficiently, you should do the following:
+
+1. [Register API with Auth0](/getting-started/set-up-api)
+2. [Define permissions for API](/dashboard/guides/apis/add-permissions-apis)
+3. [Create roles](/dashboard/guides/roles/create-roles)
+4. [Assign roles to users](/dashboard/guides/users/assign-roles-users)
+5. [Assign permissions to users](/dashboard/guides/users/assign-permissions-users), if needed.
+
+## Keep reading
+- [Manage Roles](/authorization/guides/manage-roles)
+- [Manage Role-Based Access Control Users](/authorization/guides/manage-users)
+- [Manage Role-Based Access Control Permissions](/authorization/guides/manage-permissions)
+- [Enable Role-Based Access Control (RBAC) for APIs](/dashboard/guides/apis/enable-rbac)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
+
+
diff --git a/articles/authorization/guides/manage-permissions.md b/articles/authorization/guides/manage-permissions.md
new file mode 100644
index 0000000000..508d73dbff
--- /dev/null
+++ b/articles/authorization/guides/manage-permissions.md
@@ -0,0 +1,53 @@
+---
+description: Learn how to manage permissions in a role-based access control (RBAC) system using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - rbac
+ - scopes
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Manage Role-Based Access Control Permissions
+
+This guide will show you how to manage permissions in a [role-based access control (RBAC)](/authorization/concepts/rbac) system using Auth0's Dashboard. These permissions are used with the API Authorization Core feature set.
+
+<%= include('../../_includes/_rbac_vs_extensions') %>
+
+<%= include('../_includes/_enable-authz-core') %>
+
+We provide various functions to help you manage your permissions, which you can access through either the Auth0 Dashboard or the Auth0 Management API.
+
+Using the Dashboard, you can:
+
+- [Define permissions for APIs](/dashboard/guides/apis/add-permissions-apis)
+- [Delete permissions from APIs](/dashboard/guides/apis/delete-permissions-apis)
+- [Add permissions to roles](/dashboard/guides/roles/add-permissions-roles)
+- [Assign permissions to users](/dashboard/guides/users/assign-permissions-users)
+- [View role permissions](/dashboard/guides/roles/view-role-permissions)
+- [View user permissions](/dashboard/guides/users/view-user-permissions)
+- [Remove role permissions](/dashboard/guides/roles/remove-role-permissions)
+- [Remove user permissions](/dashboard/guides/users/remove-user-permissions)
+
+Using the Management API, you can:
+
+- [Update permissions for APIs](/api/management/guides/apis/update-permissions-apis)
+- [Add permissions to roles](/api/management/guides/roles/add-permissions-roles)
+- [Assign permissions to users](/api/management/guides/users/assign-permissions-users)
+- [View role permissions](/api/management/guides/roles/view-role-permissions)
+- [View user permissions](/api/management/guides/users/view-user-permissions)
+- [Remove permissions from roles](/api/management/guides/roles/remove-role-permissions)
+- [Remove permissions from users](/api/management/guides/users/remove-user-permissions)
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Create Roles](/dashboard/guides/roles/create-roles)
+- [Register APIs with Auth0](/architecture-scenarios/mobile-api/part-2#create-the-api)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
diff --git a/articles/authorization/guides/manage-roles.md b/articles/authorization/guides/manage-roles.md
new file mode 100644
index 0000000000..28c2e56d70
--- /dev/null
+++ b/articles/authorization/guides/manage-roles.md
@@ -0,0 +1,53 @@
+---
+description: Learn how to manage roles using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - rbac
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Manage Roles
+
+This guide will show you how to manage roles using Auth0's Dashboard. Roles are used with the API Authorization Core feature set.
+
+<%= include('../../_includes/_rbac_vs_extensions') %>
+
+<%= include('../_includes/_enable-authz-core') %>
+
+We provide various functions to help you manage your roles, which you can access through either the Auth0 Dashboard or the Auth0 Management API.
+
+Using the Dashboard, you can:
+
+- [Create roles](/dashboard/guides/roles/create-roles)
+- [Edit role definitions](/dashboard/guides/roles/edit-role-definitions)
+- [Add permissions to roles](/dashboard/guides/roles/add-permissions-roles)
+- [View role permissions](/dashboard/guides/roles/view-role-permissions)
+- [Remove permissions from roles](/dashboard/guides/roles/remove-role-permissions)
+- [View role users](/dashboard/guides/roles/view-role-users)
+- [Remove users from roles](/dashboard/guides/roles/remove-role-users)
+- [Delete roles](/dashboard/guides/roles/delete-roles)
+
+Using the Management API, you can:
+
+- [Create roles](/api/management/guides/roles/create-roles)
+- [Edit role definitions](/api/management/guides/roles/edit-role-definitions)
+- [Add permissions to roles](/api/management/guides/roles/add-permissions-roles)
+- [View role permissions](/api/management/guides/roles/view-role-permissions)
+- [Remove permissions from roles](/api/management/guides/roles/remove-role-permissions)
+- [View role users](/api/management/guides/roles/view-role-users)
+- [Remove users from roles](/api/management/guides/users/remove-user-roles)
+- [Delete roles](/api/management/guides/roles/delete-roles)
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Assign Roles to Users](/dashboard/guides/users/assign-roles-users)
+- [Register APIs with Auth0](/architecture-scenarios/mobile-api/part-2#create-the-api)
+- [Add API Permissions](/dashboard/guides/apis/add-permissions-apis)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
diff --git a/articles/authorization/guides/manage-users.md b/articles/authorization/guides/manage-users.md
new file mode 100644
index 0000000000..e853000eaf
--- /dev/null
+++ b/articles/authorization/guides/manage-users.md
@@ -0,0 +1,50 @@
+---
+description: Learn how to manage users in a role-based access control (RBAC) system using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - rbac
+ - users
+ - user-profile
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Manage Role-Based Access Control Users
+
+This guide will show you how to manage users in a [role-based access control (RBAC)](/authorization/concepts/rbac) system using Auth0's Dashboard.
+
+<%= include('../../_includes/_rbac_vs_extensions') %>
+
+<%= include('../_includes/_enable-authz-core') %>
+
+We provide various functions to help you manage your users, which you can access through either the Auth0 Dashboard or the Auth0 Management API.
+
+Using the Dashboard, you can:
+- [Assign roles to users](/dashboard/guides/users/assign-roles-users)
+- [View user roles](/dashboard/guides/users/view-user-roles)
+- [Remove roles from users](/dashboard/guides/users/remove-user-roles)
+- [Assign permissions to users](/dashboard/guides/users/assign-permissions-users)
+- [View user permissions](/dashboard/guides/users/view-user-permissions)
+- [Remove permissions from users](/dashboard/guides/users/remove-user-permissions)
+
+Using the Management API, you can:
+- [Assign roles to users](/api/management/guides/users/assign-roles-users)
+- [View user roles](/api/management/guides/users/view-user-roles)
+- [Remove roles from users](/api/management/guides/users/remove-user-roles)
+- [Assign permissions to users](/api/management/guides/users/assign-permissions-users)
+- [View user permissions](/api/management/guides/users/view-user-permissions)
+- [Remove permissions from users](/api/management/guides/users/remove-user-permissions)
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Create Roles](/dashboard/guides/roles/create-roles)
+- [Register APIs with Auth0](/architecture-scenarios/mobile-api/part-2#create-the-api)
+- [Add API Permissions](/dashboard/guides/apis/add-permissions-apis)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
diff --git a/articles/authorization/index.md b/articles/authorization/index.md
new file mode 100644
index 0000000000..5b5c98e6b3
--- /dev/null
+++ b/articles/authorization/index.md
@@ -0,0 +1,38 @@
+---
+description: Understand the concept of Authorization using Auth0.
+topics:
+ - authorization
+contentType:
+ - index
+ - concept
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Authorization
+
+Authorization refers to the process of verifying what a user has access to. While often used interchangeably with [authentication](/application-auth/current), authorization represents a fundamentally different function.
+
+In authorization, a user or application is granted access to an API after the API determines the extent of the permissions that it should assign. Usually, authorization occurs after identity is successfully validated through authentication so that the API has some idea of what sort of access it should grant. For a comparison of authorization and authentication, see [Authentication and Authorization](/authorization/concepts/authz-and-authn).
+
+Authorization can be determined through the use of [policies](/authorization/concepts/policies) and [rules](/authorization/concepts/authz-rules), which can be used with [role-based access control (RBAC)](/authorization/concepts/rbac). Regardless of whether RBAC is used, requested access is transmitted to the API via scopes and granted access is returned in the issued Access Tokens.
+
+Since only the API can know all of the possible actions that it can handle, it should have its own internal access control system in which it defines its own permissions. To determine a calling application's effective permissions, an API should combine incoming scopes with the permissions assigned within its own internal access control system and make access control decisions accordingly.
+
+## Role-based access control in Auth0
+
+<%= include('../_includes/_rbac_methods') %>
+
+<%= include('../_includes/_rbac_vs_extensions') %>
+
+## Keep reading
+
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Authorization Policies](/authorization/concepts/policies)
+- [Sample Use Cases: Role-Based Access Control](/authorization/concepts/sample-use-cases-rbac)
+- [Sample Use Cases: Rules with Authorization](/authorization/concepts/sample-use-cases-rules)
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
+- [Authorization Core vs. Authorization Extension](/authorization/concepts/core-vs-extension)
+- [Authorization Extension](/extensions/authorization-extension)
+- [Troubleshooting: Role-Based Access Control and Authorization](/authorization/concepts/troubleshooting)
diff --git a/articles/authorization/reference/rbac-limits.md b/articles/authorization/reference/rbac-limits.md
new file mode 100644
index 0000000000..219e1a72b2
--- /dev/null
+++ b/articles/authorization/reference/rbac-limits.md
@@ -0,0 +1,32 @@
+---
+title: Authorization Core Limits
+description: Reference limits in place for the Authorization Core feature set.
+topics:
+ - authorization
+contentType:
+ - reference
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Authorization Core RBAC Limits
+
+The Authorization Core Role-Based Access Control (RBAC) feature set is subject to the following limits:
+
+| Feature | Limit |
+|---------|-------|
+| Roles per tenant | 1000 |
+| Scopes per API | 1000 |
+| Roles per user (directly assigned) | 50 |
+| Permissions per user (directly assigned) | 1000 |
+| Permissions per role (directly assigned) | 1000 |
+
+Note that limitations on permissions per user affect those assigned directly. Technically, a user could have more permissions than noted if the permissions were assigned to different roles and then the roles were assigned to the user.
+
+## Keep reading
+
+- [Role-Based Access Control in Auth0](/authorization#role-based-access-control-in-Auth0)
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Authorization Core vs. Authorization Extension](/authorization/concepts/core-vs-extension)
+- [How to Use Auth0's Core Authorization Feature Set](/authorization/guides/how-to)
\ No newline at end of file
diff --git a/articles/best-practices/application-settings.md b/articles/best-practices/application-settings.md
new file mode 100644
index 0000000000..b572f1c291
--- /dev/null
+++ b/articles/best-practices/application-settings.md
@@ -0,0 +1,31 @@
+---
+title: Application Settings Best Practices
+description: Learn about recommended application settings in Auth0.
+topics:
+ - best-practices
+ - configuration
+ - application
+ - settings
+contentType:
+ - reference
+useCase:
+ - best-practices
+ - application
+ - application-settings
+---
+# Application Settings Best Practices
+
+Here are some best practices for configuring [Application Settings](${manage_url}/#/applications) on the Dashboard.
+
+| Setting | Best Practice |
+| - | - |
+| Client ID | Confirm your application code uses the correct Client ID. |
+| Application Type | Make sure the correct [application type](/applications) is set in your application settings to help Auth0 check for certain security risks. |
+| First- and Third-party applications | Flag first-party and third-party applications. Third-party applications must be created using the Auth0 Management API and have the `is_first_party` attribute set to `false`. |
+| ID token expiration | Set the [ID Token expiration time](/tokens/id-tokens#token-lifetime). By default ID Tokens expire after 10 hours. Once issued, an [ID Token cannot be revoked](/tokens/guides/revoke-tokens), so instead of longer expiration times, use a short expiration time and renew the session if the user remains active. |
+| Wildcards or localhost URLs | Do not use wildcard or localhost URLs in your application callbacks or allowed origins fields. Using redirect URLs with wildcards [can make your application vulnerable to attacks](https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet). |
+| Logout redirect URLs | To redirect users after [logout](/logout), register the redirect URL in your tenant or application settings. Auth0 only redirects to whitelisted URLs after logout. If you need different redirects for each application, you can whitelist the URLs in your application settings. |
+| **Advanced Settings**: RS256 signature algorithm | Make sure that RS256 is the signature method for signing JSON Web Tokens (JWT). The JWT signature method can be found under [Applications > Settings > Advanced Settings > OAuth](${manage_url}/#/applications).|
+| **Advanced Settings**: OIDC conformant (for tenants created before 2017-12-27) | If your application is not [OIDC conformant](/api-auth/intro), [migrate your applications](/api-auth/tutorials/adoption) to be OIDC conformant. Newer tenants can only use OIDC conformant behavior. Test by turning on the OIDC conformant toggle and testing your application. |
+| **Advanced Settings**: Restrict delegation | <%= include('../_includes/_deprecate-delegation') %> If you are not using delegation, provide your application's Client ID in the **Allowed Apps / APIs** field to restrict delegation requests. |
+| **Advanced Settings**: Grant types | Turn off unneeded grant types for your application to prevent someone from issuing authorization requests for unauthorized grant types. |
diff --git a/articles/best-practices/connection-settings.md b/articles/best-practices/connection-settings.md
new file mode 100644
index 0000000000..145b4ca408
--- /dev/null
+++ b/articles/best-practices/connection-settings.md
@@ -0,0 +1,46 @@
+---
+title: Connection Settings Best Practices
+description: Learn about recommended identity provider connection settings in Auth0.
+topics:
+ - best-practices
+ - configuration
+ - settings
+ - connection
+contentType:
+ - reference
+useCase:
+ - best-practices
+ - connection
+ - connection-settings
+---
+# Connection Settings Best Practices
+
+Here are some best practices for configuring [connections](/connections). Before you set up connections, take a moment to review [what connections are](/connections) and [the basics of authentication](/application-auth) for your application type.
+
+## Use your credentials for social connections
+
+Auth0 provides [default credentials](/connections/social/devkeys) for [social connections](/connections/identity-providers-social) to help you get started. You should replace these temporary credentials with your own to avoid restrictions.
+
+## Review requested data
+
+You should review the data you are requesting from each social connection. Users must grant consent for the requested data. Requesting a lot of unnecessary data may result in users declining the authorization request out of privacy concerns.
+
+## Set password policy for database connections
+
+Configure the [password policy](/connections/database/password-strength) for your [Auth0 database connections](/connections/database) so created users have strong passwords. You can configure the password policy in the [database connection settings](${manage_url}/#/connections/database/) on the dashboard or with the [Auth0 Management API](/api/management/v2/#!/Connections/patch_connections_by_id).
+
+The password policy applies to password resets performed with the Universal Login [Page](/universal-login) as well as the [Auth0 Management API](/api/management/v2/).
+
+## Disable user signup if it's not appropriate for each database connection
+
+In your database connection settings, specify if self-service user signups should be enabled. If you enabled this during development, check if you should disable it on production tenants.
+
+Only enable this setting for production tenants if you allow end users to sign up in a self-service manner. If self-service signup is not allowed, disable the feature. You can then add users to the database connection with the Auth0 Management API.
+
+## Review applications enabled for each connection
+
+For each connection, review the list of allowed applications. Make sure there are no unintended authentication paths into an application. By default, new applications may have all of your tenant's connections enabled, which may not be appropriate.
+
+## Use RSA-SHA256 for SAML connections
+
+Configure any SAML connections to sign requests and use RSA-SHA256 as the signature algorithm. This ensures the remote SAML Identity Provider can validate whether the authentication requests came from a legitimate application or not.
diff --git a/articles/best-practices/custom-db-connections/anatomy.md b/articles/best-practices/custom-db-connections/anatomy.md
new file mode 100644
index 0000000000..1c9eccfdae
--- /dev/null
+++ b/articles/best-practices/custom-db-connections/anatomy.md
@@ -0,0 +1,74 @@
+---
+title: Custom Database Connection Anatomy Best Practices
+description: Learn about best practices for custom database connection anatomy.
+classes: topic-page
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+---
+# Custom Database Connection Anatomy Best Practices
+
+You typically use a [custom database connection](/connections/database/custom-db) to provide access to your own legacy identity store for authentication (sometimes referred to as *legacy authentication*) or perform user import through [automatic migration](/users/guides/configure-automatic-migration) (often referred to as *trickle* or *lazy* migration).
+
+::: note
+You can also use custom database connections to proxy access to an Auth0 tenant in scenarios where you use Auth0 multi-tenant architecture. For more information, see [Using Auth0 to Secure Your Multi-Tenant Applications](/design/using-auth0-with-multi-tenant-apps).
+:::
+
+You typically create and configure custom database connections using the [Auth0 Dashboard](/connections/database/custom-db/create-db-connection#step-1-create-and-configure-a-custom-database-connection). You create a database connection, and then toggle **Use my own database** to enable editing of the database action scripts. A custom database connection can also be created and configured with the Auth0 [Management API](/api/management/v2#!/Connections/post_connections) and the `auth0` strategy.
+
+
+
+As shown below, you use custom database connections as part of a login workflow to obtain user identity information from your own legacy identity store for authentication or user import, referred to as *legacy authentication*.
+
+
+
+
+
+In addition to artifacts common for all database connections types, a custom database connection allows you to configure action scripts—custom code used when interfacing with legacy identity stores. The scripts you choose to configure depend on whether you are creating a connection for legacy authentication or for automatic migration (see [Custom Database Action Script Execution](/best-practices/custom-db-connections/execution) for further details).
+
+::: panel Best Practice
+Action scripts can be implemented as anonymous functions; however, anonymous functions make it hard to debug when it comes to interpreting the call-stack generated as a result of any exceptional error conditions. For convenience, we recommend providing a function name for each action script and have supplied some [recommended names](/best-practices/custom-db-connections/execution#recommended-script-names).
+:::
+
+In a legacy authentication scenario, no new user record is created; the user remains in the legacy identity store and Auth0 uses the identity it contains when authenticating the user.
+
+::: note
+Custom database connections are also used outside of the Universal Login workflow. For example, a connection's [`changePassword`](/best-practices/custom-db-connections/execution#change-password) action script is called when a password change operation occurs for a user that resides in a legacy identity store.
+:::
+
+## Automatic migration
+
+During automatic migration, Auth0 creates a new user in an identity store (database) managed by Auth0. Auth0 uses the identity in the Auth0-managed identity store when authenticating the user. For this to occur, Auth0 first requires the user be authenticated against the legacy identity store and only if this succeeds will the new user be created in the Auth0 managed database. Auth0 creates the new user using the same id and password that were supplied during authentication.
+
+::: panel Best Practice
+User creation in an automatic migration scenario typically occurs after the **Login** action script completes. We recommend that you **do not attempt** to delete users from a legacy identity store as an inline operation within the **Login** script, but instead as an independent process. This prevents accidental user deletion should an error condition occur during migration.
+:::
+
+With automatic migration, users remain in the legacy identity store and can be deleted or archived if required. A side-effect can occur where a user is deleted from Auth0 but remains in the legacy data store. In this case, a login made by the deleted user could result in either the **Login** or **Get User** script executing and the user again migrating from the legacy identity store.
+
+::: panel Best Practice
+We recommend marking legacy store user identities as *migrated* before either **Login** or **Get User** scripts complete and prior to any eventual legacy store deletion to prevent the unintentional recreation of intentionally-deleted users.
+:::
+
+## Keep reading
+
+<%= include('../../_includes/_topic-links', { links: [
+ 'best-practices/custom-db-connections/size',
+ 'best-practices/custom-db-connections/environment',
+ 'best-practices/custom-db-connections/execution',
+ 'best-practices/error-handling',
+ 'best-practices/debugging',
+ 'best-practices/testing',
+ 'best-practices/deployment',
+ 'best-practices/performance',
+ 'best-practices/custom-db-connections/security'
+] }) %>
diff --git a/articles/best-practices/custom-db-connections/environment.md b/articles/best-practices/custom-db-connections/environment.md
new file mode 100644
index 0000000000..fa8b4ef36f
--- /dev/null
+++ b/articles/best-practices/custom-db-connections/environment.md
@@ -0,0 +1,64 @@
+---
+title: Custom Database Action Script Environment Best Practices
+description: Learn about best practices for the custom database action script environment.
+classes: topic-page
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+---
+# Custom Database Action Script Environment Best Practices
+
+Action scripts execute as a series of called JavaScript functions in an instance of a serverless Webtask container. As part of this, a specific environment is provided, together with a number of artifacts supplied by both the Webtask container and the Auth0 authentication server (your Auth0 tenant) itself.
+
+## `npm` modules
+
+Auth0 serverless Webtask containers can make use of a wide range of [`npm`](https://www.npmjs.com/) modules; `npm` modules not only reduce the overall size of action script code implementation, but also provide access to a wide range of pre-built functionality.
+
+By default, a large list of publicly available `npm` modules are [supported out-of-the-box](https://auth0-extensions.github.io/canirequire/). This list has been compiled and vetted for any potential security concerns. If you require an `npm` module that is not supported out-of-the-box, then a request can be made via the [Auth0 support portal](https://support.auth0.com/) or your Auth0 representative. Auth0 will evaluate your request to determine suitability. There is currently no support in Auth0 for the user of npm modules from private repositories.
+
+## Variables
+
+Auth0 action scripts support the notion of environment variables, accessed via what is defined as the globally-available [`configuration`](/connections/database/custom-db/create-db-connection#step-3-add-configuration-parameters) object. The `configuration` object should be treated as read-only and should be used for storing sensitive information, such as credentials or API keys for accessing external identity stores. This mitigates having security-sensitive values hard coded in an action script.
+
+The `configuration` object can also be used to support whatever [Software Development Life Cycle (SDLC)](/dev-lifecycle/setting-up-env) best practice strategies you employ by allowing you to define variables that have tenant-specific values. This mitigates hard coded values in an action script, which may change depending upon which tenant is executing it.
+
+## `global` object
+
+Auth0 serverless Webtask containers are provisioned from a pool that is associated with each Auth0 tenant. Each container instance makes available a global object, which can be accessed across all action scripts that execute within it (the container instance). The global object acts as a global variable that is unique to the container and that can be used to define information—or even functions—that can be used across all action scripts that run in it (the container instance).
+
+This means that the global object can be used to cache expensive resources, as long as those resources are not user-specific. For example, an Access Token for a third-party (e.g., logging) API that provides non user-specific functionality could be stored. Or it could be used to store an Access Token to your own non user-specific API defined in Auth0 and obtained via use of the Client Credentials flow.
+
+::: warning
+An action script may execute in any of the container instances already running or in a newly-created container instance (which may subsequently be added to the pool). There is no container affinity *per-se* for action script execution in Auth0. This means that you should avoid storing any user-specific information in the global object and should always ensure that any declaration made within the global object provides for initialization too.
+:::
+
+Each time a Webtask container is recycled, or for each instantiation of a new Webtask container, the global object it defines is reset. Thus, any declaration of assignment within the global object associated with a container should also include provision for initialization. To provide performance flexibility, serverless Webtask containers are provisioned in Auth0 on an ad-hoc basis and are also subject to various recycle policies. In general, we recommend that you do not consider the life of a global object to be anything more than 20 minutes.
+
+## Custom database connection environment checklist
+
+* Make sure that your database has the appropriate fields to store user profiles attributes, such as **id**, **nickname**, **email**, and **password**. See [Normalized User Profile](/users/normalized) for details on Auth0's user profile schema and the expected fields. Also, see [Update User Profile Using Your Database](/users/guides/update-user-profiles-using-your-database) for more information.
+* You can use return errors resulting from your custom database connection for troubleshooting purposes. See [Custom Database Error Handling and Troubleshooting](/connections/database/custom-db/error-handling) for basic troubleshooting steps.
+* The `id` (or alternatively `user_id`) property in the returned user profile will be used by Auth0 to identify the user. If you are using multiple custom database connections, then the **id** value **must be unique across all the custom database connections** to avoid **user ID** collisions. Our recommendation is to prefix the value of **id** with the connection name (omitting any whitespace). See [Identify Users](/users/normalized/auth0/identify-users) for more information on user IDs.
+* Latency will be greater compared to Auth0-hosted user stores.
+* The database or service must be reachable from the Auth0 servers. You will need to configure inbound connections if your store is behind a firewall.
+
+## Keep reading
+
+<%= include('../../_includes/_topic-links', { links: [
+ 'best-practices/custom-db-connections/execution',
+ 'best-practices/error-handling',
+ 'best-practices/debugging',
+ 'best-practices/testing',
+ 'best-practices/deployment',
+ 'best-practices/performance',
+ 'best-practices/custom-db-connections/security'
+] }) %>
\ No newline at end of file
diff --git a/articles/best-practices/custom-db-connections/execution.md b/articles/best-practices/custom-db-connections/execution.md
new file mode 100644
index 0000000000..3b2f2284a6
--- /dev/null
+++ b/articles/best-practices/custom-db-connections/execution.md
@@ -0,0 +1,181 @@
+---
+title: Custom Database Action Script Execution Best Practices
+description: Learn about best practices for custom database action script execution.
+classes: topic-page
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+---
+# Custom Database Action Script Execution Best Practices
+
+As described in [Custom Database Connection Anatomy](/best-practices/custom-db-connections/anatomy), a custom database connection type allows you to configure action scripts, which contain custom code that is used when interfacing with your legacy identity store. Each action script is essentially a named JavaScript function that is passed a number of parameters, with the name of the function and the parameters passed dependent on the script in question.
+
+Action script execution supports the asynchronous nature of JavaScript, and constructs such as [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) objects and the like can be used. Asynchronous processing effectively results in suspension-pending completion of an operation, and an Auth0 serverless Webtask container typically has an approximately 20-second execution limit, after which the container may be recycled. Recycling of a container due to this limit will prematurely terminate operation, ultimately resulting in an error condition being returned (as well as resulting in a potential reset of the `global`(/best-practices/rules#global-object) object).
+
+The `callback` function supplied to each action script effectively acts as a signal to indicate completion of operation. An action script should complete immediately following a call to the callback function—either implicitly or, preferably, by explicitly executing a (JavaScript) `return` statement—and should refrain from any other operation. The (Auth0) supplied callback function must be called exactly once; calling the function more than once within an action script will lead to unpredictable results and/or errors.
+
+::: note
+Where callback is executed with no parameters, as in `callback()`, the implication is that function has been called as though `callback(null)` had been executed.
+:::
+
+If an action script is making use of asynchronous processing, then a call to the (Auth0) supplied `callback` function must be deferred to the point where asynchronous processing completes and must be the final thing called. Asynchronous execution will result in a (JavaScript) callback being executed after the asynchronous operation is complete; this callback is typically fired at some point after the main (synchronous) body of a JavaScript function completes.
+
+Failure to execute the `callback` function will result in a stall of execution and ultimately, in an error condition being returned. The action script must call the `callback` function exactly once. The `callback` function must be called at least once to prevent stall of execution; however, it must not be called more than once or unpredictable results and/or errors will occur.
+
+## Keep in mind
+
+* Script templates, including the default templates, are not used until you click **Save**. This is true even if you only modify one script and haven't made changes to any others. You must click **Save** at least once for all the scripts to be in place.
+* Action scripts can be implemented as anonymous functions; however, anonymous functions make it hard in debugging situations when it comes to interpreting the call-stack generated as a result of any exceptional error condition. For convenience, we recommend providing a function name for each action script and have supplied some [recommended names](/best-practices/custom-db-connections/execution#recommended-script-names).
+* The total size of implementation for any action script should not exceed 100 kB. The larger the size, the more latency is introduced due to the packaging and transport process employed by the Auth0 serverless Webtask platform, and this will have an impact on the performance of your system. Note that the 100 kB limit does not include any `npm` modules that may be referenced as part of any require statements.
+* Database scripts run in the same Webtask container, which is shared with all other extensibility points (such as rules, webtasks, or other databases) belonging to the same Auth0 domain. Therefore, you must carefully code for error handling and throttling.
+* An action script may execute in any of the container instances already running or in a newly-created container instance (which may subsequently be added to the pool). There is no container affinity for action script execution in Auth0. This means that you should avoid storing any user-specific information in the `global` object and should always ensure that any declaration made within the `global` object provides for initialization too. Each time a Webtask container is recycled, or for each instantiation of a new Webtask container, the `global` object it defines is reset. Thus, any declaration of assignment within the `global` object associated with a container should also include provision for initialization. To provide performance flexibility, serverless Webtask containers are provisioned in Auth0 on an *ad-hoc* basis and are also subject to various recycle policies. In general, we recommend that you do not consider the life of a `global` object to be anything more than 20 minutes.
+
+## General script checklist
+
+Use the following checklist to make sure your scripts achieve the results you intend.
+
+* When indicating an error condition, we recommend using the `Error` object to provide Auth0 with a clear indication of the error condition. For example, `callback(new Error(“an error message”))`.
+
+* **Set a `user_id` on the returned user profile that is consistent for the same user every time.**
+ This is important in the non-migration scenario, because if you return a different `user_id` you will end up with duplicated users.
+
+* **If using a `username`, ensure that you aren't returning the same email address for two different users in the `get_user` or `login` script.**
+ Auth0 will produce an error if you do this, but it is better to catch it in the script itself.
+
+* **If setting `app_metadata`, call it `metadata` in the script.**
+ To support backwards compatibility, `app_metadata` is called `metadata` in custom DB scripts. If you don't use `metadata` in the script, you will get an error where `app_metadata` will work, but if you use the API to merge `app_metadata` with a user, it will appear as if all of your metadata was lost.
+
+ ::: note
+ `user_metadata` is not affected by this and can simply be called `user_metadata`.
+ :::
+
+* **If using Auth0 to do machine-to-machine to the legacy database, restrict access to that audience with a rule.**
+ As with any API that you create, if you create it solely for client credentials, then you will want to restrict access to the API in a rule. By default, Auth0 gives you a token for any API if you authenticate successfully and include the audience. Someone could intercept the redirect to authorize and add the audience to your legacy database API. If you don’t block this in a rule, they will get an Access Token.
+
+ ::: note
+ You can also update the API to expect the sub of the token to end in `@clients`.
+ :::
+
+* **Determine if they are accessing their database directly versus through an API.**
+ This item is not a requirement; it is a recommended best practice. A database interface is extremely open. You should add protections between an API endpoint and your database. Most people do not expose their database directly to the internet. Though you can whitelist Auth0 IPs, those IPs are shared in the cloud environment. In general, Auth0 recommends that you protect your database from too many actors directly talking to it. The alternative is to create a simple API endpoint that each script within Auth0 can call. That API can be protected using an Access Token. You can use the client credentials flow to get the Access Token from within the rules.
+
+* **If enabling trickle migration, ensure the following:**
+
+ * **The `Login` script and the `get_user` script both return the same user profile.**
+ Because of the two different flows (logging in or using forgot password), if the `get_user` and `login` script return different user profiles, then depending on how a user migrates (either by logging in directly or using the forgot password flow), they will end up with different profile information in Auth0.
+
+ * **If setting `app_metadata` or `user_metadata`, use a rule to fetch the metadata if it is missing.**
+ The metadata is not migrated until https://YOUR_TENANT.auth0.com/login/callback is called. However, the user credentials are migrated during the post to `usernamepassword/login`. This means that if the browser is killed or computer dies on a user after they have posted to `usernamepassword/login`, but before login/callback, then they will have a user in the Auth0 database, but their app and user metadata are lost. It is really important, therefore, to create a rule that looks a lot like your `get_user` script to fetch the profile if app and user metadata are blank. This should only execute once per user at most (and usually never).
+
+ * **Use a rule to mark users as migrated.**
+ This is not a hard requirement, but it does protect against one scenario in which a user changes their email address, then changes it back to the original email address. A rule should call out to the legacy database to mark the user as being migrated in the original database so that `get_user` can return false.
+
+### Identity provider tokens
+
+If the `user` object returns the `access_token` and `refresh_token` properties, Auth0 handles these slightly differently from other pieces of user information. They will be stored in the `user` object's `identities` property, so retrieving them using the API therefore requires an additional scope: `read:user_idp_tokens`.
+
+```js
+{
+ "email": "you@example.com",
+ "updated_at": "2019-03-15T15:56:44.577Z",
+ "user_id": "auth0|some_unique_id",
+ "nickname": "a_nick_name",
+ "identities": [
+ {
+ "user_id": "some_unique_id",
+ "access_token": "e1b5.................92ba",
+ "refresh_token": "a90c.................620b",
+ "provider": "auth0",
+ "connection": "custom_db_name",
+ "isSocial": false
+ }
+ ],
+ "created_at": "2019-03-15T15:56:44.577Z",
+ "last_ip": "192.168.1.1",
+ "last_login": "2019-03-15T15:56:44.576Z",
+ "logins_count": 3
+}
+```
+
+## Individual script template best practices
+
+### Recommended script names
+
+You can use action scripts as anonymous functions; however, anonymous functions make it hard to debug when it comes to interpreting the call-stack generated as a result of any exceptional error conditions. For convenience, we recommend providing a function name for each action script and have supplied some recommended names below.
+
+| Script Template | Recommended Name |
+| --- | --- |
+| Login | `login` |
+| Get User | `getUser` |
+| Create | `create` |
+| Verify | `verify` |
+| Change Password | `changePassword` |
+| Delete | `deleteUser` |
+| Change Email | `changeEmail` |
+
+### Login action scripts
+
+The [Login script](/connections/database/custom-db/templates/login) implements the function executed each time a user is required to authenticate.
+
+* The profile returned by the **Login** script for a user should be consistent with the profile returned in the **Get User** script and vice versa.
+* If you are providing `app_metadata` as part of the user profile, then you should refer to this as "metadata" in the profile object returned. Failure to do this will result in a loss of the metadata if any modifications are made to the users’ `app_metadata` in the future.
+* While a user does not need to use an email address to login, it is recommended best practice that they have an email address defined against their user profile. This ensures that Auth0 out-of-box functionality works as designed.
+* To update `name`, `nickname`, `given_name`, `family_name`, and/or `picture` attributes associated with the root of the normalized user profile, you must configure user profile sync so that user attributes will be updated from the identity provider. Auth0 does not support update of these attributes for a custom database connection used for legacy authentication.
+
+### Get User action scripts
+
+The [Get User](/connections/database/custom-db/templates/get-user) script implements the function executed to determine the current state of existence of a user.
+
+* When creating users, Auth0 calls the **Get User** script before the **Create** script. If you are creating new users, be sure to implement both database action scripts.
+
+### Create action scripts
+
+The [Create](/connections/database/custom-db/templates/create) script implements the function executed to create a user in your database.
+
+* If the custom database connection has `Requires Username` enabled, then `username` also needs to be used by any subsequent `login` or `getUser` script execution, so you should store it in the legacy identity store.
+* Unlike with `login`, `app_metadata` is specified as-is and will not be renamed as `metadata`.
+* If you create and use [custom fields](/libraries/custom-signup#using-the-api) during the registration process, these properties are included in the `user` object as well.
+
+### Verify action scripts
+
+The [Verify](/connections/database/custom-db/templates/verify) script implements the function executed to mark the verification status of a user’s email address in the legacy identity store.
+
+* The `verify` function is called when a user clicks on the link in the verification email sent by Auth0. Change in email verification status influenced by other operations, such as via user profile modification in the Auth0 Dashboard, is performed via the [Change Email](/connections/database/custom-db/templates/change-email) script.
+
+### Change Password action scripts
+
+The [Change Password](/connections/database/custom-db/templates/change-password) script implements the function executed to change the password associated with the user identity in the legacy identity store.
+
+* While it’s not mandatory to implement the `changePassword` function, it is a recommended best practice. The `changePassword` function is required for the password reset workflow recommended for [better customer experience](https://auth0.com/learn/password-reset/).
+
+### Delete action scripts
+
+The [Delete](/connections/database/custom-db/templates/delete) script implements the function executed to delete the specified user identity from the legacy identity store.
+
+* Deleting a user using the Auth0 Dashboard or the Auth0 Management API performs deletion of both the user profile and the user identity. If you do not implement this script correctly, then this will not be done as an atomic operation, which may leave a user identity still in existence even after the user’s profile has been removed. Conversely, deleting a user identity outside of Auth0 will typically leave a disconnected (orphaned) profile in Auth0 that has no associated user identity. This may cause unpredictable issues.
+
+### Change Email action scripts
+
+The [Change Email](/connections/database/custom-db/templates/change-email) script implements the function executed when a change in the email address or email address status for a user occurs.
+
+* If you change any aspect of a connection via the Dashboard in Auth0 and that connection makes use of a **Change Email** script, then the script will be deleted.
+
+## Keep reading
+
+<%= include('../../_includes/_topic-links', { links: [
+ 'best-practices/error-handling',
+ 'best-practices/debugging',
+ 'best-practices/testing',
+ 'best-practices/deployment',
+ 'best-practices/performance',
+ 'best-practices/custom-db-connections/security'
+] }) %>
diff --git a/articles/best-practices/custom-db-connections/index.md b/articles/best-practices/custom-db-connections/index.md
new file mode 100644
index 0000000000..27a5165634
--- /dev/null
+++ b/articles/best-practices/custom-db-connections/index.md
@@ -0,0 +1,51 @@
+---
+title: Custom Database Connection and Action Script Best Practices
+description: Learn about best practices for custom database connections and database action scripts.
+classes: topic-page
+toc: true
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+---
+# Custom Database Connection and Action Script Best Practices
+
+::: panel Feature availability
+Only **Enterprise** subscription plans include the ability to use a custom database for authentication requests. For more information, see [Auth0 pricing plans](https://auth0.com/pricing).
+:::
+
+[Extensibility](/extend-integrate) provides the capability to add custom login in Auth0 as a mechanism for building out last-mile solutions for Identity and Access Management (IdAM). Auth0 extensibility comes in several forms:
+
+- [Rules](/rules): Run when artifacts for user authenticity are generated. For example:
+ - An [ID Token](/tokens/id-token) in OpenID Connect (OIDC)
+ - An Access Token in [OAuth 2.0](/protocols/oauth2)
+ - An [assertion in SAML](/protocols/saml/saml-configuration/saml-assertions#use-rules)
+- [Hooks](/hooks): Provide additional extensibility when there is an exchange of non-user-related artifacts and when user identities are created such as pre-user registration and post-user registration.
+- Scripts for both [Custom Database Connections](/connections/database#using-your-own-user-store) and [Migrations](/connections/database#migrating-to-auth0-from-a-custom-user-store): Used to [integrate with an existing user identity store](/connections/database/custom-db) or where [automatic user migration](https://auth0.com/learn/migrate-user-database-auth0/) from an independent or *legacy* identity store are required.
+
+Each extensibility type uses Node.js running on the Auth0 platform in an Auth0 tenant.
+
+Whatever the use case, Auth0 extensibility provides comprehensive and sophisticated capability to tailor IdAM operations to your exact requirements. However, if not utilized in the right way, this can open up the potential for improper or unintended use which can lead to problematic situations down the line. In an attempt to address matters ahead of time, this document provides best practice guidance to both designers and implementers, and we recommend reading it in its entirety at least once, even if you've already started your journey with Auth0.
+
+## Keep reading
+
+<%= include('../../_includes/_topic-links', { links: [
+ 'best-practices/custom-db-connections/anatomy',
+ 'best-practices/custom-db-connections/size',
+ 'best-practices/custom-db-connections/environment',
+ 'best-practices/custom-db-connections/execution',
+ 'best-practices/error-handling',
+ 'best-practices/debugging',
+ 'best-practices/testing',
+ 'best-practices/deployment',
+ 'best-practices/performance',
+ 'best-practices/custom-db-connections/security'
+] }) %>
\ No newline at end of file
diff --git a/articles/best-practices/custom-db-connections/security.md b/articles/best-practices/custom-db-connections/security.md
new file mode 100644
index 0000000000..dbbfb1593c
--- /dev/null
+++ b/articles/best-practices/custom-db-connections/security.md
@@ -0,0 +1,46 @@
+---
+title: Custom Database Connection Security Best Practices
+description: Learn about best practices for custom database connection security.
+classes: topic-page
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+---
+# Custom Database Connection Security Best Practices
+
+## Access legacy identity storage via custom API
+
+We recommend that you implement an API to provide least privilege to your legacy identity storage rather than simply opening up general access via the internet.
+
+Protecting legacy identity storage from general access is a recommended best practice. Exposing a (legacy identity) database directly to the internet, for example, can be extremely problematic: database interfaces for SQL and the like are extremely open in terms of functionality, which violates the principle of least privilege when it comes to security.
+
+The alternative is to create a simple (custom) API—protected via use of an Access Token—that each action script can call. This would act as the interface to the legacy identity store. Client credentials grant flow can then be used to obtain an Access Token from within a script, and this can be subsequently cached for re-use within the `global` object to improve performance. The API can then provide a discrete number of protected endpoints that perform only the legacy (identity) management functionality required (e.g., read user, change password).
+
+By default, Auth0 will give you a token for any API if you authenticate successfully and include the appropriate audience. Restricting access to the legacy identity store API by restricting access token allocation via use of a Rule will prevent unauthorized usage and will mitigate a number of attack vector scenarios, such as where redirect to `/authorize` is intercepted and the audience to the API is added.
+
+::: warning
+Restricting access to the API via Rule will mitigate attack vector scenarios, such as where redirect to `/authorize` is intercepted and the audience to the API is added, and will ensure that only access using specific client credentials is granted.
+:::
+
+## Whitelist access to legacy identity storage
+
+Whether managing access to legacy identity storage via custom API or using the native interface provided, you should restrict access to the list of [IP addresses associated with your Auth0 tenant](/guides/ip-whitelist). Whitelisting in this manner constrains access to the legacy identity store and ensures that only custom database actions scripts defined in Auth0 are permitted.
+
+::: warning
+The Auth0 IP address whitelist is shared between all Auth0 tenants defined to a region. Never use the whitelist as the sole method of securing access to your legacy identity store; doing so could open up potential security vulnerabilities allowing unauthorized access to your users.
+:::
+
+## Keep reading
+
+* [Security Bulletins](/security/bulletins)
+* [Auth0 Security](/security)
+* [Token Storage](/tokens/concepts/token-storage)
diff --git a/articles/best-practices/custom-db-connections/size.md b/articles/best-practices/custom-db-connections/size.md
new file mode 100644
index 0000000000..1c0137d08f
--- /dev/null
+++ b/articles/best-practices/custom-db-connections/size.md
@@ -0,0 +1,33 @@
+---
+title: Custom Database Action Script Size Best Practices
+description: Learn about best practices for custom database action script size.
+classes: topic-page
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+---
+# Custom Database Action Script Size Best Practices
+
+As a best practice, we recommend that the total size of any action script not exceed 100 kB. The larger the size, the more latency is introduced due to the packaging and transport process employed by the Auth0 serverless Webtask platform, and this will have an impact on the performance of your system. Note that the 100 kB limit does not include any `npm` modules that may be referenced as part of any `require` statements.
+
+## Keep reading
+
+<%= include('../../_includes/_topic-links', { links: [
+ 'best-practices/custom-db-connections/environment',
+ 'best-practices/custom-db-connections/execution',
+ 'best-practices/error-handling',
+ 'best-practices/debugging',
+ 'best-practices/testing',
+ 'best-practices/deployment',
+ 'best-practices/performance',
+ 'best-practices/custom-db-connections/security'
+] }) %>
\ No newline at end of file
diff --git a/articles/best-practices/debugging.md b/articles/best-practices/debugging.md
new file mode 100644
index 0000000000..1e27d330bb
--- /dev/null
+++ b/articles/best-practices/debugging.md
@@ -0,0 +1,72 @@
+---
+title: Debugging Best Practices
+description: Learn about best practices for debugging.
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+ - rules
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+ - rules
+---
+# Debugging Best Practices
+
+Out of the box, [runtime debugging](/rules/guides/debug) of a rule is typically achieved via the use of console logging by using the [console.log](https://developer.mozilla.org/en-US/docs/Web/API/Console/log) facility. There is no interactive debugging of a rule available within the Auth0 platform (though one could employ the testing [automation](/best-practices/testing#automation) technique described below in conjunction with some external interactive source-debugging facility).
+
+::: panel Best Practice
+Adding sufficient line (i.e., `//`) or block (i.e., `/* */`) comments to a rule, particularly around non-obvious functionality, is invaluable to both code debugging and also code understanding, particularly as there are many occasions where the initial implementer of a rule may not be the same person responsible for maintaining it going forward.
+:::
+
+By default, console log output is unavailable for display during normal execution. However, the [Real-time Webtask Logs extension](/extensions/realtime-webtask-logs) can be used to display all console logs in real-time for all implemented extensibility in an Auth0 tenant, including rules. The real-time console log display provided by the extension includes all `console.log` output, [`console.error`](https://developer.mozilla.org/en-US/docs/Web/API/Console/error) output, and [`console.exception`](https://developer.mozilla.org/en-US/docs/Web/API/Console/error) output.
+
+In a production environment, debug logging isn’t something that’s desirable all the time; given the [performance](/best-practices/performance) considerations associated with rules, it would not be prudent to have it continuously enabled. However, in a development or testing environment, the option to enable it on a more continuous basis is much more desirable. Further, excessive debug logging could create substantial “noise”, which could make identifying problems that much harder.
+
+Modifying a rule to enable or disable debug logging dependent on the environment would be messy and prone to error. Instead, the environment [configuration](/best-practices/rules#environment-variables) object can be leveraged to implement conditional processing in a fashion similar to the following:
+
+```js
+ function NPClaims(user, context, callback) {
+ /*
+ * This rule (https://auth0.com/docs/rules) is used to derive
+ * effective claims associated with the Normalized User Profile:
+ * https://auth0.com/docs/user-profile/normalized/auth0
+ */
+ var LOG_TAG = '[NORMALIZED_PROFILE_CLAIMS]: ';
+ var DEBUG = configuration.DEBUG ? console.log : function () {};
+ DEBUG(LOG_TAG, "identities=", user.identities);
+ user.user_metadata = user.user_metadata || {};
+
+ //
+ user.family_name =
+ user.family_name ||
+ user.identities.filter(function(identity) {
+ /* Filter out identities which do not have anything synonymous with
+ * Family Name
+ */
+ return(
+ identity.profileData &&
+ identity.profileData.family_name);
+ }).map(function(identity) {
+ return identity.profileData.family_name;
+ })[0];
+ DEBUG(LOG_TAG, "Computed user.family_name as '", user.family_name, "'");
+ .
+ .
+
+ //
+ return callback(null, user, context);
+ }
+```
+
+In the example above, a `DEBUG` environment configuration variable has been created, which can be set to `true` or `false` depending on the execution environment (e.g., production, testing, development). The setting of this variable is used to determine when debug logging is performed. Further, a `DEBUGLEVEL` environment` configuration` variable, say, could be created, which could be used to control the debugging log level (e.g., verbose, medium, sparse).
+
+The above example also demonstrates declaration of a named function. For convenience, providing a function name—using some compact and unique naming convention—can assist with diagnostic analysis. Anonymous functions make it hard in debugging situations to interpret the call-stack generated as a result of any [exceptional error](/best-practices/error-handling#exceptions) condition and providing a unique function name addresses this.
+
+### Static analysis
+The rule editor in the Auth0 dashboard provides some rudimentary syntax checking and analysis of rule semantics. However, no provision is made for more complex static code analysis, such as overwrite detection, loop detection, or vulnerability detection. To address this, consider leveraging use of third-party tooling—such as [JSHint](https://jshint.com/about/), [SonarJS](https://www.sonarsource.com/products/codeanalyzers/sonarjs.html), or [Coverity](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html)—in conjunction with rule [testing](/best-practices/testing) as part of your [deployment](/best-practices/deployment) automation process.
diff --git a/articles/best-practices/deployment.md b/articles/best-practices/deployment.md
new file mode 100644
index 0000000000..3a6d0fb104
--- /dev/null
+++ b/articles/best-practices/deployment.md
@@ -0,0 +1,36 @@
+---
+title: Deployment Best Practices
+description: Learn about best practices for deployment.
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+ - rules
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+ - rules
+---
+# Deployment Best Practices
+
+Coding a rule within the Auth0 Dashboard rule editor is a great way to implement and test while still in the development stage. However, when it comes time to deploy into automated test and/or production environments, a more automated mechanism is required; copying and pasting code between Auth0 tenants is not a satisfactory method to employ.
+
+Out of the box, Auth0 provides a number of facilities for automated deployment of rule extensibility assets between Auth0 tenant environments. The Auth0 [GitHub](/extensions/github-deploy), [GitLab](/extensions/gitlab-deploy), and [Bitbucket](/extensions/bitbucket-deploy) extensions provide the ability to update rule assets from the respective third-party version control system—both manually and in many instances, automatically (i.e., when a change in the version control system is detected).
+
+In addition, the Auth0 [Deploy CLI](/extensions/deploy-cli) tool can be used to automate deployment between Auth0 tenants. Deploy CLI works with files stored in the file system together with the Auth0 Management API and provides the capability to allow the export of rule assets from an Auth0 tenant, as well as import of them into an Auth0 tenant. Further, the tool provides for programmatic control over rule ordering and rule environment [configuration](/best-practices/rules#environment-variables) as part of deployment automation. In many ways, the Deploy CLI is like a Swiss Army knife when it comes to rule extensibility deployment in Auth0.
+
+::: panel Best Practice
+As a best practice, you should use the Auth0 [Deploy CLI](/extensions/deploy-cli) tool in almost all cases involving deployment to test or production environments. While the extensions can provide automated detection of changes deployed to the respective version control system, the Deploy CLI tool allows precise control of what’s deployed when, where, and how.
+:::
+
+## Versioning
+
+There is no version management when it comes to rules in Auth0; changes made to a rule deployed to an Auth0 tenant will be made live immediately because any change written instantly overwrites what is already there. It is therefore recommended that:
+
+* use of version control, such as Git via GitHub or the like, is employed to provide change management capability
+* use of a separate [Test Tenant](/dev-lifecycle/setting-up-env) in Auth0 is employed (as part of testing strategy) to provide safe testing of any rule/rule changes before deploying to production
diff --git a/articles/best-practices/error-handling.md b/articles/best-practices/error-handling.md
new file mode 100644
index 0000000000..f1a6b5a06a
--- /dev/null
+++ b/articles/best-practices/error-handling.md
@@ -0,0 +1,73 @@
+---
+title: Error Handling Best Practices
+description: Learn about best practices for error handling.
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+ - rules
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+ - rules
+---
+# Error Handling Best Practices
+
+Error conditions returned from API calls and the like must be handled and processed in an appropriate manner. Failure to do so can lead to unhandled [exception](#exceptions) situations, resulting in premature termination of pipeline execution and ultimately in an authentication error being returned.
+
+::: panel Best Practice
+Use of [`console.error`](https://developer.mozilla.org/en-US/docs/Web/API/Console/error) to log any error conditions encountered is a recommended best practice and can also assist with any potential [debugging](/best-practices/debugging). We also recommend sending error conditions to an external service, such as [Splunk](/monitoring/guides/send-events-to-splunk), to provide better visibility and diagnosis of anomalous operation.
+:::
+
+As described in [Execution Best Practices](/best-practices/custom-db-connections/execution), there are time constraints regarding how much time a rule has available in which to execute. If recovery from an error condition is not possible (or probable) within this time period, then an error condition should be explicitly returned; this is as simple as completing rule execution by returning an instance of a Node [Error](https://nodejs.org/api/errors.html#errors_class_error) object, as in:
+
+```js
+ return callback(new Error('some description'));
+```
+
+Alternatively, an instance of the Auth0-specific `UnauthorizedError` can be returned, which will cause an `unauthorized` error condition with the supplied error description to be returned to the application that initiated authentication—e.g., the application from which redirect to the `/authorize` endpoint was initiated. This allows an application to offer (conditional) retry capability, and additionally, provides capability to implement rule(s) which can be used to [deny access based on certain conditions](/rules/references/legacy#deny-access-based-on-a-condition). For a description of other common authentication error conditions in Auth0, see the [Auth0 SDK library documentation](/libraries/error-messages):
+
+```js
+ return callback(new UnauthorizedError('some description'), user, context);
+```
+
+::: panel Best Practice
+The `UnauthorizedError` object only returns the description supplied. If you wish to employ specific processing for specific unauthorized error conditions, then we’d recommend you format your descriptions to include some easily accessible “error code” information (e.g., `'[00043] - my specific error description'`).
+:::
+
+## Exceptions
+
+Unexpected error conditions must also be handled. Unexpected error conditions, such as uncaught JavaScript exceptions, will typically result in the premature termination of pipeline execution, which will ultimately result in an error in authentication being returned.
+
+::: panel Best Practice
+Use of [`console.exception`](https://developer.mozilla.org/en-US/docs/Web/API/Console/error) to log any exceptional error conditions encountered is a recommended best practice and can also assist with any potential [debugging](/best-practices/debugging). We also recommend sending error conditions to an external service, such as [Splunk](/monitoring/guides/send-events-to-splunk), to provide better visibility and diagnosis of anomalous operation.
+:::
+
+For situations involving asynchronous operations, a `catch` handler when utilizing [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) object processing is imperative. `Promise` object processing can also be effective for error handling during non-asynchronous operations. As illustrated below, a `Promise` object can be used to wrap, say, a synchronous function call, making it easier to implement cascaded error handling via use of [promise chaining](https://javascript.info/promise-error-handling) and the like.
+
+```js
+ return new Promise(function(resolve, reject) {
+ jwt.verify(
+ token,
+ secret,{
+ clockTolerance: 5},
+ function(err, decoded) {
+ if (err) {
+ reject(err);
+ } else {
+ resolve(decoded);
+ }
+ });
+ });
+```
+
+Alternatively, use of [`try...catch`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) processing can be used to handle JavaScript exceptions that occur during synchronous operation. Setup of this type of exception handling can often incur performance costs, so should be used sparingly; rule [performance](/best-practices/performance) should be as optimal as possible. A more pragmatic approach is to implement processing that prevents exceptions from occurring rather than handling them once they have occurred.
+
+::: panel Best Practice
+Use of uninitialized objects is a common cause of exceptions. To guard against this, prefer to include provision for initialization (e.g., `user.user_metadata = user.user_metadata || {}`) as part of any declaration in cases where the existence of an object is in question. In a rule, taking steps to prevent an exception from occurring in the first place is a best practice and is typically less costly in terms of performance and resource usage than implementing exception handling.
+:::
diff --git a/articles/best-practices/index.md b/articles/best-practices/index.md
new file mode 100644
index 0000000000..1cc32296ee
--- /dev/null
+++ b/articles/best-practices/index.md
@@ -0,0 +1,29 @@
+---
+title: Best Practices
+description: Learn the best practices to consider when using Auth0.
+classes: topic-page
+topics:
+ - best-practices
+contentType:
+ - index
+ - reference
+useCase:
+ - best-practices
+---
+
+# Best Practices
+
+Our best practice guides have information on how to configure and use Auth0. We'll share recommended configuration settings, and show you how to get the most out of different Auth0 features.
+
+<%= include('../_includes/_topic-links', { links: [
+ 'best-practices/operations',
+ 'best-practices/application-settings',
+ 'best-practices/connection-settings',
+ 'best-practices/metadata-best-practices',
+ 'best-practices/custom-db-connections',
+ 'best-practices/rules',
+ 'best-practices/search-best-practices',
+ 'best-practices/tenant-settings',
+ 'best-practices/token-best-practices',
+ 'best-practices/user-data-storage-best-practices'
+] }) %>
\ No newline at end of file
diff --git a/articles/best-practices/metadata-best-practices.md b/articles/best-practices/metadata-best-practices.md
new file mode 100644
index 0000000000..ca2ff01771
--- /dev/null
+++ b/articles/best-practices/metadata-best-practices.md
@@ -0,0 +1,121 @@
+---
+description: Best practices for metadata in Auth0.
+topics:
+ - best-practices
+ - metadata
+toc: true
+contentType: reference
+useCase:
+ - manage users
+ - best-practices
+ - metadata
+---
+
+# Metadata Best Practices
+
+## Metadata field names
+
+* Avoid periods, ellipses, and dynamic metadata field names.
+
+* Metadata field **names** must not contain a dot. For example, use of the following field name would return a Bad Request (400) error:
+
+ ```json
+ {
+ "preference.color": "pink"
+ }
+ ```
+
+ One way of handling this limitation is to nest attributes:
+
+ ```json
+ {
+ "preference": {
+ "color": "pink"
+ }
+ }
+ ```
+
+* Alternately, you can use any delimiter that is not `.` or `$`. However, you can the `.` delimiter in the data **values** such as in the below example:
+
+ ```json
+ {
+ "preference": "light.blue"
+ }
+ ```
+
+* Do not use dynamic field names. For example, instead of using the following structure:
+
+ ```json
+ "participants": {
+ "Alice" : {
+ "role": "sender"
+ },
+ "Bob" : {
+ "role": "receiver"
+ }
+ }
+ ```
+
+ Use this:
+
+ ```json
+ "participants": [
+ {
+ "name": "Alice",
+ "role": "sender"
+ },
+ {
+ "name" : "Bob",
+ "role": "receiver"
+ }
+ ]
+ ```
+
+## Metadata data types
+
+Use a consistent data type each time you create or update a given metadata field. For example, if you use `user.user_metadata.age = "23"` for one user and `user.user_metadata.age = 23` for another user, it will cause issues when retrieving the data.
+
+## Metadata storage and size limits
+
+* Both `app_metadata` and `user_metadata` are together limited to a size of 16 MB total per user. Metadata storage is not designed to be a general purpose data store, and you should still use your own external storage facility when possible. When using Rules and/or the Management Dashboard, your metadata limits may be lower.
+
+* When setting the `user_metadata` field using the [Authentication API's Signup endpoint](/api/authentication?javascript#signup), you are limited to a maximum of 10 `String` fields and 500 characters. For an example of working with metadata during a custom signup process, see [Custom Signup > Using the API](/libraries/custom-signup#using-the-api).
+
+## Customize emails with metadata
+
+Store any information that you want to use to customize Auth0 emails in metadata. Use `user_metadata` if the user is allowed to change the field's value, such as information used to determine the language for an email.
+
+## App metadata restrictions
+
+::: warning
+User credentials such as Access Tokens, Refresh Tokens, and additional passwords should not be stored in `app_metadata`, as these will be visible to any Auth0 Dashboard administrator.
+:::
+
+The `app_metadata` field should **not** contain any of these properties:
+
+* `__tenant`
+* `_id`
+* `blocked`
+* `clientID`
+* `created_at`
+* `email_verified`
+* `email`
+* `globalClientID`
+* `global_client_id`
+* `identities`
+* `lastIP`
+* `lastLogin`
+* `loginsCount`
+* `metadata`
+* `multifactor_last_modified`
+* `multifactor`
+* `updated_at`
+* `user_id`
+
+## Keep reading
+
+* [Metadata](/users/concepts/overview-user-metadata)
+* [Manage User Metadata](/users/guides/manage-user-metadata)
+* [Update Metadata with the Management API](/users/guides/update-metadata-properties-with-management-api)
+* [User Metadata in Rules](/rules/current/metadata-in-rules)
+* [User Data Storage Best Practices](/best-practices/user-data-storage-best-practices)
diff --git a/articles/best-practices/operations.md b/articles/best-practices/operations.md
new file mode 100644
index 0000000000..247a6f1f1a
--- /dev/null
+++ b/articles/best-practices/operations.md
@@ -0,0 +1,48 @@
+---
+title: General Usage and Operations Best Practices
+description: Learn about best practices for general operations in Auth0.
+topics:
+ - best-practices
+contentType:
+ - index
+ - reference
+useCase:
+ - best-practices
+---
+# General Usage and Operations Best Practices
+
+Here are some recommended best practices for general Auth0 usage and operation.
+
+## Capture log files
+
+Auth0 keeps tenant [logs](/logs) for a limited amount of time. To get log data and store it elsewhere, you can use the [Management API](/api/management/v2#!/Logs/get_logs), [stream the logs](/logs/streams) to an external service or use one of the [available extensions](/extensions#export-auth0-logs-to-an-external-service) for services such as Loggly or Splunk.
+
+## Set up your own email provider and customize email templates
+
+[Auth0 provides a test email provider](/email) so you can test default welcome and email verification messages during tenant setup. The test provider can only send a limited amount of emails, so you should [configure your own mail server](/email/providers). Additionally, we recommend a unique email provider account per tenant. Sharing an email account between tenants can be a potential source of problems or outages for one tenant when making changes to the service intended for another.
+
+Also, make sure to [configure and customize the templates](/email/templates) for emails sent from Auth0. These include email verification messages, welcome messages, password reset messages, et cetera. For custom templates provide a "from” address, a clear subject, your custom content, and a link timeout for emails with a link (such as a password reset link).
+
+## Subscribe to updates on the Auth0 status page
+
+Head over to the [Auth0 status page](https://status.auth0.com/) and sign up for notifications. If there are any Auth0 outages, you or your support staff will be notified.
+
+## Store custom code in a source code repository
+
+If you have custom code for rules, hooks, custom database scripts, or webtasks, store it in a source code repository such as Github for version and audit control. Auth0 has [extensions to help deploy code stored on external repositories](/extensions#deploy-hosted-pages-rules-and-database-connections-scripts-from-external-repositories).
+
+If you have a full continuous integration/continuous deployment pipeline, use the [Auth0 Deploy CLI tool](https://github.com/auth0/auth0-deploy-cli) for greater flexibility.
+
+## Store configuration values in dashboard
+
+If your rules, hooks, custom database scripts, or webtasks require configuration values (such as credentials or API keys), you should store them in the Auth0 dashboard. Storing configuration values in the dashboard [makes migrating configuration](/dev-lifecycle/setting-up-env#migration) between tenants easier.
+
+## Whitelist Auth0 public IP addresses
+
+If your rules, hooks, custom database scripts, or webtasks call a service in your intranet or behind another firewall, be sure to whitelist the Auth0 public IP addresses. This lets requests from those IP addresses through. You can find the IP addresses for each region in your Auth0 dashboard, where you edit rules, hooks, or custom DB scripts.
+
+## Run tenant configuration checks
+
+The [Auth0 Support Center](https://support.auth0.com/) provides a configuration checker tool. Run the configuration checker periodically during development and again before you launch.
+
+To run the configuration check, go to [Auth0 Support Center -> Tenants](https://support.auth0.com/tenants/public) and select the gear icon and choose **Run Production Check**.
diff --git a/articles/best-practices/performance.md b/articles/best-practices/performance.md
new file mode 100644
index 0000000000..d5b04b4c48
--- /dev/null
+++ b/articles/best-practices/performance.md
@@ -0,0 +1,64 @@
+---
+title: Performance Best Practices
+description: Learn about best practices for performance.
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+ - rules
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+ - rules
+---
+# Performance Best Practices
+
+Rules execute as part of a pipeline where artifacts for authenticity are generated, as described in [Anatomy Best Practices](/best-practices/custom-db-connections/anatomy). As such, an enabled rule will execute for every login operation (interactive or otherwise), every silent authentication, and every time a user-credentials-related Access Token is generated for an API call. This means that even in small scale deployments, performance can be a concern, which will only be exacerbated as the scale of deployment increases.
+
+## Avoid unnecessary execution
+
+Prefer to implement execution based on conditional logic. For example, to run a rule for only specific applications, check on a specific [`clientID`](/rules/references/context-object) or for specific [`clientMetadata`](/rules/references/context-object)—especially when checking against a single `clientMetadata` value, common across multiple applications. Using `clientMetadata` can also make adding new clients (as well as reading rule code) easier, especially if you have a large number of applications defined, by reducing the code changes or configuration values needed between environments.
+
+::: note
+Client metadata for an application can be set manually via the Dashboard by going to [Application Settings -> Advanced Settings -> Application Metadata](${manage_url}/#/applications/) or programmatically via use of the [Auth0 Management API](/api/management/v2#!/Clients/patch_clients_by_id).
+:::
+
+## Exit early
+For optimal performance, write rules that complete as soon as possible. For example, if a rule has three checks to decide if it should run, use the first check to eliminate the majority of cases, followed by the check to eliminate the next largest set of cases, and so on and so forth. At the end of each check, remember to execute the [callback](/best-practices/rules#callback-function) function, ideally combined with a (JavaScript) `return` in order to exit the (rule) function.
+
+## Minimize API requests
+Calls to APIs, especially calls to third-party APIs, can slow down login response time and can cause rule timeout failures due to call latency, ultimately leading to authentication error situations. We recommend keeping API requests to a minimum wherever possible within a rule and avoiding excessive calls to paid services](#limit-calls-to-paid-services). We also recommend you avoid potential security exposure by [limiting what is sent](/best-practices/rules#do-not-send-entire-context-object-to-external-services) to any API—third party or otherwise.
+
+::: panel Best Practice
+The [`global`](/best-practices/rules#global-object) object can be used to cache information from API calls, which can subsequently be used across all rules that execute in the pipeline. Prefer to use this to store information instead of repeatedly calling an API. Additionally, the [`global` object](/best-practices/rules#global-object) can also be used to cache other information between executing rules.
+:::
+
+### Limit calls to paid services
+If you have rules that call paid services, such as sending messages via Twilio, make sure that you only use those services when necessary. This not only provides performance enhancement, but also helps to avoid extra charges. To help reduce calls to paid services:
+
+* Disallow public sign-ups to reduce the number of users who can sign up and trigger calls to paid services
+* Ensure that a rule only gets triggered for an authorized subset of users or other appropriate conditions. For example, you may want to add logic that checks if a user has a particular email domain, role/group, or subscription level before triggering the call to the paid service.
+
+### Limit calls to the Management API
+Prefer to avoid calls to the Auth0 Management API. The Auth0 Management API is [rate limited](/policies/rate-limits#management-api-v2), which will still be a consideration even when using the `auth0` object (so be sure to use it sparingly). In addition, Management API functions take varying degrees of time to perform, so will incur varying degrees of latency; executing [user search](/api/management/v2#!/Users/get_users) functionality, for example, should be kept to a minimum and performed only where absolutely necessary—even when executed via the `auth0` object.
+
+### Avoid calls to the Management API for Connection-related details
+
+We have expanded [connection-related properties](/rules/references/context-object) available to the rules [`context`](/best-practices/rules#context-object) object, so you can obtain connection info from the `context` object instead of needing to call the Auth0 Management API.
+
+To see this in action, if you are using the **Check if user email domain matches configured domain** rule template, check out the latest version [on Github](https://github.com/auth0/rules/blob/master/src/rules/check-domains-against-connection-aliases.js) or in the [Auth0 Dashboard](${manage_url}/#/rules/new). Note: the recent changes will not alter functionality but will improve the performance of rules that had once relied on calls to the Management API.
+
+Removing calls to the Management API (as well as the extra call required to get the appropriate Access Token) will make your rule code perform better and be more reliable.
+
+## Consider use of explicit timeouts when making API calls
+
+When calling APIs or accessing external services, consider specifying explicit timeout(s). The specific timeout value you choose will typically vary based on your use case, but in general, choosing one that is as low as possible—while bearing in mind the performance characteristics of the external service—is advised.
+
+::: panel Best Practice
+Whether you choose to use explicit timeouts or implicit timeout processing, always be sure to cater to [error](/best-practices/error-handling) and/or [exception](/best-practices/error-handling#exceptions) conditions that may occur as a result of any timeout period expiration.
+:::
diff --git a/articles/best-practices/rules.md b/articles/best-practices/rules.md
new file mode 100644
index 0000000000..6a7472057b
--- /dev/null
+++ b/articles/best-practices/rules.md
@@ -0,0 +1,378 @@
+---
+title: Rules Best Practices
+description: Learn about best practices for writing and managing Auth0 Rules.
+toc: true
+topics:
+ - best-practices
+ - rules
+contentType: reference
+useCase:
+ - best-practices
+ - rules
+---
+
+# Rules Best Practices
+
+[Rules](/rules) can be used in a [variety of situations](/rules#what-can-i-use-rules-for-) as part of the authentication pipeline where protocol specific artifacts are generated:
+
+- an ID Token in [OpenID Connect (OIDC)](/protocols/oidc)
+- an Access Token in [OAuth 2.0](/protocols/oauth2)
+- an [assertion in SAML](/protocols/saml/saml-configuration/saml-assertions#use-rules)
+
+A new pipeline in which rules execute is created for each authentication request.
+
+Auth0 provides a number of [pre-existing Rules/Rule templates](https://github.com/auth0/rules) to help you achieve your goal(s). You may also want to [build your own Rule(s)](/rules/guides/create) to support your specific functionality requirements. You can modify a pre-existing rule template or choose to start from scratch using one of our [samples](/rules/references/samples). Either way, there are a number of best practices that you’ll want to adopt to ensure that you achieve the best possible outcome.
+
+The image below shows the [Auth0 Dashboard](/dashboard) with a number of enabled and disabled rules for a specific [Auth0 Tenant](/getting-started/the-basics#account-and-tenants). Enabled rules—those with the green toggle—are those rules that are active and will execute as part of a pipeline. Disabled rules—those with the greyed-out toggle—on the other hand, won't.
+
+
+
+## Anatomy
+
+A rule is essentially an anonymous JavaScript function that is passed three parameters: a [`user`](#user-object) object, a [`context`](#context-object) object, and a [`callback`](#callback-function) function.
+
+```js
+ function (user, context, callback) {
+ // TODO: implement your rule
+ return callback(null, user, context);
+ }
+ ```
+
+::: note
+**Do not** add a trailing semicolon at the end of the function declaration as this will break rule execution.
+:::
+
+::: panel Best Practice
+Anonymous functions make it hard to interpret the call-stack generated as a result of any [exceptional error](/best-practices/error-handling#exceptions) condition. For convenience, use compact and unique naming conventions to assist with diagnostic analysis (e.g., `function MyRule1 (user, context, callback) {...}`).
+:::
+
+Rules execute in the pipeline associated with the generation of artifacts for authenticity that forms part of the overall Auth0 engine. When a pipeline is executed, all enabled rules are packaged together in the order in which they are listed and sent as one code blob to be executed as an Auth0 serverless Webtask.
+
+
+
+## Size
+
+We recommend that the total size of implementation for all enabled rules should not exceed 100 kB. The larger the size, the more latency is introduced due to the packaging and transport process employed by the Auth0 serverless Webtask platform, and this will have an impact on the performance of your system. Note that the 100 kB limit does not include any [`npm`](https://www.npmjs.com/) modules that may be referenced as part of any [`require`](https://nodejs.org/api/modules.html#modules_require_id) statements.
+
+## Order
+
+The order in which rules are displayed in the [Auth0 Dashboard](/dashboard) dictates the order in which the rules will be executed. This is important because one rule may make one or more definitions within the [environment](/best-practices/custom-db-connections/environment) associated with execution that another rule may depend upon. In this case, the rule making the definition(s) should execute before the rule that makes use of it.
+
+::: panel Best Practice
+Run expensive rules that call APIs (including the Auth0 Management API) as late as possible. If you have other, less expensive rules that could cause an `unauthorized` access determination, then you should run these first.
+:::
+
+## Environment
+
+Rules execute as a series of called JavaScript functions in an instance of an Auth0 serverless Webtask __container__. As part of this, a specific environment is provided, together with a number of artifacts supplied by both the container and the Auth0 authentication server (your Auth0 tenant) itself.
+
+### `npm` modules
+
+Auth0 serverless Webtask containers can make use of a wide range of [`npm`](https://www.npmjs.com/) modules; npm modules not only reduce the overall size of rule code implementation, but also provide access to a wide range of pre-built functionality.
+
+By default, a large list of publicly available npm modules are [supported out-of-the-box](https://auth0-extensions.github.io/canirequire/). This list has been compiled and vetted for any potential security concerns. If you require an npm module that is not supported, you can request one at the [Auth0 support](https://support.auth0.com/) portal or via your Auth0 representative. Auth0 evaluates requests to determine suitability. There is currently no support in Auth0 for the use of `npm` modules from private repositories. New packages are typically added on a 2 week cycle when requested. Existing packages are rarely removed as this would cause breaking changes in rules. Keep in mind, Auth0 packages and versions are stored on an internal registry and are not in sync with `npm`.
+
+::: panel Best Practice
+When using `npm` modules to access external services, [keep API requests to a minimum](/best-practices/performance#minimize-api-requests), [avoid excessive calls to paid services](/best-practices/performance#limit-calls-to-paid-services), and avoid potential security exposure by [limiting what is sent](#do-not-send-entire-context-object-to-external-services). For more information, see [Performance Best Practices](/best-practices/performance) and [Security Best Practices](/best-practices/custom-db-connections/security).
+
+When requiring a module in a rule, if the version is not specified, the package manager uses the first version it finds on the internal list. A version may be specified to force the package manager to use a non-default version. This allows rule code to take advantage of fixes or features from the specified version that are not available in the default module version.
+:::
+
+### Environment variables
+
+Auth0 Rules support environment variables, accessed via the globally available [configuration](/rules/guides/configuration) object. Configuration should be treated as read-only and should be used for [storing sensitive information](#store-security-sensitive-values-in-rules-settings), such as credentials or API keys for external service access. This mitigates having security-sensitive values hard-coded in a rule. It can also be used to support [Software Development Life Cycle (SDLC)](/dev-lifecycle/setting-up-env) best practice strategies you employ by allowing you to define variables that have tenant-specific values. This mitigates hard-code values in a rule which may change depending upon which tenant is executing it.
+
+### `global` object
+
+Auth0 serverless Webtask containers are provisioned from a pool that's associated with each Auth0 tenant. Each container instance makes available the `global` object, which can be accessed across all rules that execute within the container instance. The `global` object acts as a global variable and can be used to define information, or to even define functions, that can be used across all rules (that run in the container) irrespective of the pipeline instance:
+
+```js
+ global.tokenVerify = global.tokenVerify || function(token, secret) {
+ /* The 'jwt.verify' function is synchronous, however wrapping with a promise
+ * provides for better error management and integration within the logic
+ * flow.
+ */
+ return new Promise(function(resolve, reject) {
+ jwt.verify(
+ token,
+ secret,{
+ clockTolerance: 5},
+ function(err, decoded) {
+ if (err) {
+ reject(err);
+ } else {
+ resolve(decoded);
+ }
+ });
+ });
+ };
+```
+
+The `global` object can also be used to cache expensive resources, such as an Access Token for a third-party (e.g., logging) API that provides non user-specific functionality or an Access Token to your own API defined in Auth0 and obtained by using [Client Credentials](/flows/concepts/client-credentials) flow.
+
+Rules can run more than once when a pipeline is executed, and this depends on the [context](#context-object) of operation. For each context in which a rule is run, an existing container instance is either provisioned from the Auth0 tenant pool or *may* be instantiated anew. For each instantiation of a new Webtask container, the `global` object is reset. Thus, any declaration within the `global` object should also include provision for initialization (as shown above), ideally with that declaration being made as early as possible (i.e., in a rule that runs early in the execution [order](#order)).
+
+### `auth0` object
+
+The `auth0` object is a specially-restricted instance of [`ManagementClient`](https://github.com/auth0/node-auth0#management-api-client) (defined in the [node-auth0](https://github.com/auth0/node-auth0) Node.js client library) and provides limited access to the [Auth0 Management API](/api/management/v2). It is primarily used for [updating metadata](/rules/guides/metadata#update-metadata) associated with the [`user`](#user-object) object from within a rule.
+
+As well as being restricted (i.e., supporting a limited number of `ManagementClient` methods for `user` access only), the [Access Token](/tokens/concepts/access-tokens) associated with the `auth0` object has scopes limited to `read:users` and `update:users`. Typically, all of this is sufficient for the majority of operations we recommend being performed from within a rule. However, if you need access to the full range of supported methods, and/or access to additional scope(s), then you will need to employ an alternative means of [access to the Management API](/api/management/v2/tokens).
+
+::: note
+Alternative access to the Management API from within a rule is typically achieved by instantiating an independent instance of the [`ManagementClient`](https://github.com/auth0/node-auth0#management-api-client). This will give you access to all current capabilities, including logic like automatic retries on `429` errors as a result of [rate limiting policy](/policies/rate-limits). In addition, if you only require the default scopes, then you can even initialize the new instance using the Access Token associated with the `auth0` object.
+:::
+
+Like the [`context`](#context-object) object (described below), the `auth0` object contains security-sensitive information, so you should not pass it to any external or third-party service. Further, the Auth0 Management API is both [rate limited](/policies/rate-limits#management-api-v2) and subject to latency, so you should be judicious regarding [how often calls are made](/best-practices/performance#minimize-api-requests).
+
+::: panel Best Practice
+Use the `auth0` object (and any other mechanisms for calling the Auth0 Management API) sparingly and use adequate [exception](/best-practices/error-handling#exceptions) and [error](/best-practices/error-handling) handling to prevent unexpected interruption of pipeline execution.
+:::
+
+## Execution
+
+Each rule is executed as a JavaScript function called in the [order](#order) defined. The next rule in order won’t execute until the previous rule has completed. In addition, the rule pipeline only executes for workflows that involve _user_ credentials; the rule pipeline **does not** execute during [Client Credentials flow](/api-auth/tutorials/adoption/client-credentials) (which is instead supported via use of the [Client Credentials Exchange](/hooks/concepts/credentials-exchange-extensibility-point) hook).
+
+In pipeline terms, a rule completes when the [`callback`](#callback-function) function supplied to the rule is called. Failure to call the function results in a stall of pipeline execution, and ultimately in an error being returned. Each rule must call the `callback` function **exactly** once.
+
+Rule execution supports the asynchronous nature of JavaScript, and constructs such as [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) objects and the like can be used. Asynchronous processing effectively results in suspension of a pipeline pending completion of the asynchronous operation. An Auth0 serverless Webtask container typically has a circa 20-second execution limit, after which the container may be recycled. Recycling of a container due to this limit will prematurely terminate a pipeline—suspended or otherwise—ultimately resulting in an error in authentication being returned (as well as resulting in a potential reset of the [`global`](#global-object) object).
+
+::: panel Best Practice
+Setting `context.redirect` triggers a [redirection](#redirection) once all rules have completed (the redirect is not forced at the point it is set). While all rules must complete within the execution limit of the Webtask container for the redirect to occur, the time taken as part of redirect processing *can* extend beyond that limit. We recommend that redirection back to Auth0 via the `/continue` endpoint should ideally occur within _one hour_. Redirection back to the `/continue` endpoint will also cause the creation of a new container in the context of the current pipeline, in which all rules will again be run.
+:::
+
+Asynchronous execution will result in a (JavaScript) callback being executed after the asynchronous operation is complete. This callback is typically fired at some point after the main (synchronous) body of a JavaScript function completes. If a rule is making use of asynchronous processing, then a call to the (Auth0) supplied [`callback`](#callback-function) function must be deferred to the point where asynchronous processing completes and must be the final thing called. As discussed above, the (Auth0) supplied `callback` function must be called exactly once; calling the function more than once within a rule will lead to unpredictable results and/or errors.
+
+### `context` object
+
+The [`context`](/rules/references/context-object) object provides information about the context in which a rule is run (such as client identifier, connection name, session identifier, request context, protocol, etc). Using the context object, a rule can determine the reason for execution. For example, as illustrated in the sample fragment below, [`context.clientID`](/rules/references/context-object#properties-of-the-context-object) as well as [`context.protocol`](/rules/references/context-object#properties-of-the-context-object) can be used to implement conditional processing to determine when rule logic is executed. The sample also shows some best practices for [exception handling](/best-practices/error-handling#exceptions), use of [`npm` modules](/best-practices/custom-db-connections/environment#npm-modules) (for `Promise` style processing), and the [`callback`](#callback-object) object.
+
+```js
+ switch (context.protocol) {
+ case 'redirect-callback':
+ return callback(null, user, context);
+ break;
+
+ default: {
+ user.app_metadata = user.app_metadata || {};
+ switch(context.clientID) {
+ case configuration.PROFILE_CLIENT: {
+ user.user_metadata = user.user_metadata || {};
+ Promise.resolve(new
+ Promise(function (resolve, reject) {
+ switch (context.request.query.audience) {
+ case configuration.PROFILE_AUDIENCE: {
+ switch (context.connection) {
+ .
+ .
+ }
+ } break;
+ .
+ .
+ })
+ )
+ .then(function () {
+ .
+ .
+ })
+ .catch(function (error) {
+ return callback(new UnauthorizedError("unauthorized"), user, context);
+ });
+ } break;
+
+ default:
+ return callback(null, user, context);
+ break;
+
+ } break;
+```
+
+::: warning
+We highly recommend reviewing best practices when [using contextual bypass logic for Multi-Factor Authentication checking](#contextual-bypass-for-multi-factor-authentication-mfa-). For example, **serious security flaws** can surface if use of MFA is predicated on `context.request.query.prompt === 'none'`. In addition, the content of the `context` object is **security sensitive**, so you should [**not** directly pass the object to any external or third-party service](#do-not-send-entire-context-object-to-external-services).
+:::
+
+#### Redirection
+
+It may not be practical to collect information from a user as part of a login flow in situations where there are many applications and you want a centralized service to manage that, or if you are using a SPA and you want to prevent the user from getting an access token under certain conditions. In these cases, having a centralized way to collect information or provide a challenge to a user is necessary.
+
+Auth0 allows you to redirect the user to any URL where you can collect information from that user and then return the user to the `/continue` endpoint where they can complete the original `/authorize` request that triggered the redirect. This is a powerful capability, and depending on the use case, the impact of doing it wrong can be anywhere from innocuous to leaving a security vulnerability in the application. As such, it is important to ensure that this is done correctly.
+
+In most use cases, a redirect rule is in use to prompt the user to make some change to their profile such as:
+- forcing a password change
+- verifying their email
+- adding information to their profile
+
+We recommend that the rule check for some flag or value in the user's `app_metadata`, then redirect to an application that does its own `/authorize` call to Auth0 and make any changes to the user's metadata and redirect the user back to Auth0. This works great for any profile changing redirects or anything that does not need to restrict the user from logging in.
+
+[Redirect from rule](/rules/guides/redirect) allows you to implement custom authentication flows that require additional user interaction triggered by [context.redirect](/rules/references/context-object#properties-of-the-context-object). Redirect from rule can only be used when calling the [`/authorize`](/api/authentication#login) endpoint.
+
+::: panel Best Practice
+Redirection to your own hosted user interface is performed before a pipeline completes and can be triggered *only once* per `context.clientID` context. Redirection should only [use HTTPS](#always-use-https) when executed in a production environment, and additional parameters should be kept to a minimum to help mitigate [common security threats](/security/common-threats). Preferably, the Auth0-supplied `state` is the only parameter supplied.
+:::
+
+Once redirected, your own hosted user interface executes in a user authenticated context, and obtains authenticity artifacts by the virtue of Auth0 SSO. Obtaining these artifacts—e.g., an ID Token in [OpenID Connect (OIDC)](/protocols/oidc), and/or an Access Token in [OAuth 2.0](/protocols/oauth2)—is achieved by using a `context.clientID` context **that is not** the one which triggered redirect. To do this, redirect to the `/authorize` endpoint. In the case of a SPA for example, use [silent authentication](/libraries/auth0js/v9#using-checksession-to-acquire-new-tokens). This creates a new pipeline that causes all rules to execute again, and you can use the `context` object within a rule to perform conditional processing.
+
+Upon completion of whatever processing is to be performed, pipeline execution continues by redirecting the user back to Auth0 via the `/continue` endpoint (and specifying the `state` supplied). This causes all rules to execute again within the current pipeline, and you can use the `context` object within a rule to perform conditional processing checks.
+
+::: panel Storing Data
+Beware of storing too much data in the Auth0 profile. This data is intended to be used for authentication and authorization purposes. The metadata and search capabilities of Auth0 are not designed for marketing research or anything else that requires heavy search or update frequency. Your system is likely to run into scalability and performance issues if you use Auth0 for this purpose. A better approach is to store data in an external system and store a pointer (the user ID) in Auth0 so that backend systems can fetch the data if needed. A simple rule to follow is to store only items that you plan to use in rules to add to tokens or make decisions.
+:::
+
+::: warning
+Passing information back and forth in the front channel opens up surface area for bad actors to attack. This should definitely be done only in conditions where you must take action in the rule (such as rejecting the authorization attempt with `UnauthorizedError`).
+:::
+
+### `user` object
+
+The [`user`](/rules/references/user-object) object provides access to a cached copy of the user account (a.k.a. [user profile](/users/concepts/overview-user-profile)) record in Auth0. The object provides access to information regarding the user without the need to access the Auth0 Management API—access which is both [rate limited](/policies/rate-limits) and subject to latency.
+
+While the contents of the `user` object can be modified—for example, one rule could make a change which another rule could use to influence its execution—any changes made will not be persisted. There may be occasions when it becomes necessary to persist, say, [updates to metadata](/rules/guides/metadata#update-metadata) associated with a user, and the [`auth0`](#auth0-object) object can be used to perform such operations where required.
+
+::: note
+Updating a user via use of the `auth0` object ultimately results in a call to the Auth0 Management API. As the Auth0 Management API is both [rate limited](/policies/rate-limits) and subject to latency, caution should be exercised regarding when and how often updates are performed.
+:::
+
+The [`context`](#context-object) object contains the `primaryUser` property which refers to the user identifier of the primary user. This user identifier will typically be the same as `user_id` property in the root of the `user` object. The primary user is the user that is returned to the Auth0 engine when the rule pipeline completes, and the `user_id` is a unique value generated by Auth0 to uniquely identify the user within the Auth0 tenant. This `user_id` should be treated as an opaque value.
+
+There are occasions when `primaryUser` must be updated as the primary user may change—i.e., the user returned to the Auth0 engine will be different from the user on rule pipeline entry. On such occasions, a rule must update `primaryUser` to reflect the new primary user identifier. Note that this change *will not* affect any subsequent rule executed in the current instance of the pipeline; the `user` object will remain unchanged.
+
+#### Identities
+
+The `user` object also contains a reference to the identities associated with the user account. The `identities` property is an array of objects, each of which contain properties associated with the respective identity as known to the identity provider (for example, the `provider` name, associated `connection` in Auth0, and the `profileData` obtained from the identity provider during the last authentication using that identity). [Linking user accounts](/users/guide/concepts/overview-user-account-linking) creates multiple entries in the array.
+
+Each identity in the `identities` array also contains a `user_id` property. This property is the identifier of the user as known to the identity provider. While the `user_id` property in the root of the `user` object *may* also include the identifier of the user as known to the identity provider, as a best practice, use of the `user_id` property in an array identity should be preferred. The `user_id` in the root of the user object should be treated as an opaque value and should not be parsed.
+
+#### Metadata
+
+The `user_metadata` property and the `app_metadata` property refer to the two different aspects of the [metadata](/users/concepts/overview-user-metadata) associated with a user. Both the `user_metadata` property and the `app_metadata` property provide access to cached copies of each.
+
+::: warning
+Authorization-related attributes for a user—such as role(s), group(s), department, and job codes—should be stored in `app_metadata` and not `user_metadata`. This is because `user_metadata` can essentially be modified by a user, whereas `app_metadata` cannot.
+:::
+
+There may be occasions when it becomes necessary to persist, say, [updates to metadata](/rules/guides/metadata#update-metadata) associated with a user, and the [`auth0`](#auth0-object) object can be used to perform such operations where required. When updating either metadata object, it is important to be judicious regarding what information is stored: in line with [metadata best practice](/users/concepts/overview-user-metadata#user-metadata-best-practices), be mindful of excessive use of metadata, which can result in increased latency due to excessive processing within the pipeline. Use of the `auth0` object also results in a call to the Auth0 Management API, so caution should be exercised regarding when and how often updates are performed since the Auth0 Management API is both [rate limited](/policies/rate-limits) and subject to latency.
+
+### `callback` function
+
+The `callback` function supplied to a rule effectively acts as a signal to indicate completion of the rule. A rule should complete immediately following a call to the callback function, either implicitly or by explicitly executing a (JavaScript) `return` statement, and should refrain from any other operation.
+
+Failure to call the function will result in a stall of pipeline execution, and ultimately in an error condition being returned. Each rule then must call the `callback` function exactly once;. Calling it once prevents the stall of the pipeline, but more could cause unpredictable results or errors.
+
+```js
+function (user, context, callback) {
+ getRoles(user.user_id, (err, roles) => {
+ if (err) return callback(err);
+
+ context.idToken['https://example.com/roles'] = roles;
+
+ return callback(null, user, context);
+ });
+}
+```
+
+As can be seen in the example above, the `callback` function can be called with up to three parameters. The first parameter is mandatory and provides an indication of the status of rule operation. The second and third parameters are optional and represent the user and the context to be supplied to the next rule in the pipeline. If these are specified, then it is a recommended best practice to pass the [`user`](#user-object) and [`context`](#context-object) object (respectively) as supplied to the rule.
+
+::: panel Best Practice
+While it can be acceptable to modify certain contents of either the `user` or the `context` object for certain situations, as a recommended best practice you should refrain from passing a newly-created instance of either the `user` or the `context` object. Passing anything other than a `user` or `context` object will have unpredictable results and may lead to an [exception](/best-practices/error-handling#exceptions) or [error](/best-practices/error-handling) condition.
+:::
+
+The status parameter should be passed as either `null`, an instance of an `Error` object, or an instance of an `UnauthorizedError` object. Specifying null will permit the continuation of pipeline processing, while any of the other values will terminate the pipeline; an `UnauthorizedError` signals [denial of access and allows information to be returned to the originator of the authentication operation](/rules/references/legacy#deny-access-based-on-a-condition) regarding the reason why access is denied. Passing any other value for any of these parameters will have unpredictable results and may lead to an exception or error condition.
+
+As authentication has already occurred, any early exit of the pipeline with an (authorization) error will _not_ impact the authenticated session within the browser; subsequent redirects to [`/authorize`](/api/authentication#login) will typically result in an automatic login. The early exit of the pipeline simply stops tokens et al from being generated. One option is for the application to redirect to the `/v2/logout` endpoint of in the Authentication API, if required, to force termination of the Auth0 session in the browser.
+
+::: warning
+Any call to the [`/logout`](/api/authentication#logout) endpoint could be interrupted, so explicit Auth0 session termination is not guaranteed. This is important, as any explicit condition that caused an `unauthorized` error must be re-checked in any subsequent rule pipeline execution, and it should not be possible to bypass these condition check(s) through any other conditions (such as [`prompt===none`](/api-auth/tutorials/silent-authentication)).
+:::
+
+## Security
+
+### Always use HTTPS
+
+Always use HTTPS, not HTTP, when making calls to external services or when executing [redirect](#redirection) as part of your rule implementation.
+
+### Store security sensitive values in rule Settings
+
+Security-sensitive information, such as credentials or API keys, should be stored in your [rule settings](${manage_url}/#/rules) where they'll be obfuscated, encrypted, and available via the [`configuration`](#configuration-object) object. Do not store these values as literals in your rules code. For example, do not write code like this:
+
+```js
+const myApiKey = 'abc123';
+```
+
+Instead, prefer to store (secret) information so that it's accessible via the [`configuration`](#configuration-object) object:
+
+```js
+const myApiKey = configuration.myApiKey;
+```
+
+### Do not send entire `context` object to external services
+
+For rules that send information to an external service, make sure you are not sending the entire [context](#context-object) object, since this object may contain tokens or other sensitive data. For rules that send information to external services, you should only send a *subset* of the less sensitive attributes from the `context` object when and where necessary.
+
+::: warning
+In a similar fashion, avoid passing **any** aspect of the [`auth0`](#auth0-object) object outside of a rule.
+:::
+
+### Check if an email is verified
+
+You can check to see if a user's email address is verified in a rule:
+
+```js
+function (user, context, callback) {
+ // Access should only be granted to verified users.
+ if (!user.email || !user.email_verified) {
+ return callback(new UnauthorizedError('Access denied.'));
+ }
+ .
+ .
+}
+```
+
+However, if you want to execute different code depending on the company the user belongs to, you **should not rely on the email domain**, but instead on data that can link the user to the identity provider they authenticated with (the connection or identity-provider -specific fields such as Azure’s **tenant id**).
+
+### Check for exact string matches
+
+For rules that determine access control based on a particular string, such as an email domain, check for an exact string match instead of checking for a substring match. If you check only for a substring, your rule may not function as you intend. For example, in:
+
+```js
+if( _.findIndex(connection.options.domain_aliases, function(d){
+ return user.email.indexOf(d) >= 0;
+}
+```
+
+the code (above) would return `true` given emails such as:
+* `user.domain.com@not-domain.com`
+* `"user@domain.com"@not-domain.com` (quotes included)
+
+which may not be as desired. Instead, prefer to perform exact matches using code such as:
+
+```js
+const emailSplit = user.email.split('@');
+const userEmailDomain = emailSplit[emailSplit.length - 1].toLowerCase();
+```
+
+For further explanation, see the **Check if user email domain matches configured domain rule template** [on GitHub](https://github.com/auth0/rules/blob/master/src/rules/check-domains-against-connection-aliases.js) or via the [Auth0 dashboard](${manage_url}/#/rules/new).
+
+### Contextual bypass for Multi-Factor Authentication (MFA)
+
+[Multi-Factor Authentication (MFA)](/mfa) provides an additional layer of security in order to guard against unauthorized access. From a user experience perspective, this typically requires additional user interaction to provide a second authentication factor—i.e., typically presenting some additional credential(s) or authorizing some form of access request.
+
+There are situations, though, when it may be desirable to bypass MFA for a user who has been designated as requiring multi-factor authentication. For instance, it maybe desirable to bypass MFA if a user has already presented both primary and secondary factors as part of authentication in the current browser context. Contextual checking in this way can help improve the user experience. However, if not done properly, it can open up serious security loop-holes which could lead to subsequent security breaches due to MFA being skipped. We therefore recommend that you observe the following guidance when considering whether to employ contextual bypass of MFA or not:
+
+::: panel Best Practice
+As a recommended best practice, use of `allowRememberBrowser` or `context.authentication` should be the only options considered for contextual bypass when using out-of-box MFA. Setting `allowRememberBrowser` to `true` lets users check a box so they will only be [prompted for multi-factor authentication periodically](/mfa/guides/customize-mfa-universal-login#change-the-frequency-of-authentication-requests), whereas [`context.authentication`](/rules/references/context-object) can be used safely and accurately to determine when MFA was last performed in the current browser context; you can see some sample use of `context.authentication` in the out-of-box supplied rule, [Require MFA once per session](https://github.com/auth0/rules/blob/master/src/rules/require-mfa-once-per-session.js).
+:::
+
+* **do not perform MFA bypass** based on conditional logic related to [silent authentication](/api-auth/tutorials/silent-authentication) (e.g., `context.request.query.prompt === 'none'`)
+* **do not perform MFA bypass** based on conditional logic using some form of device fingerprinting (e.g., where `user.app_metadata.lastLoginDeviceFingerPrint === deviceFingerPrint`)
+* **do not perform MFA bypass** based on conditional logic using geographic location (e.g., where `user.app_metadata.last_location === context.request.geoip.country_code`)
+
+#### Context checking when using custom MFA providers
+
+In a similar fashion to that already discussed, we recommend following guidance provided in the items listed above for any rules that redirect users to custom multi-factor authentication providers. For example, for custom providers, there's no safe way to effectively bypass MFA during silent authentication because [redirection](#redirection) (required for custom MFA) will always fail in silent authentication situations.
+
+## Keep reading
+
+* [Error Handling](/best-practices/error-handling)
+* [Debugging](/best-practices/debugging)
+* [Testing](/best-practices/testing)
+* [Deployment](/best-practices/deployment)
+* [Performance](/best-practices/performance)
diff --git a/articles/best-practices/search-best-practices.md b/articles/best-practices/search-best-practices.md
new file mode 100644
index 0000000000..a9819abbe0
--- /dev/null
+++ b/articles/best-practices/search-best-practices.md
@@ -0,0 +1,35 @@
+---
+title: User Search Best Practices
+description: Learn about best practices when searching for users in Auth0
+topics:
+ - users
+ - user-management
+ - search
+contentType: reference
+useCase:
+ - manage-users
+---
+# User Search Best Practices
+
+When running user searches:
+
+* You'll need a token to make requests to the Management API. Check out [Access Tokens for the Management API](/api/management/v2/tokens) for more information.
+* To perform user search requests, the `read:users` scope is required.
+* To get the latest search results, use an **immediately consistent** endpoint during authentication processes such as [Get Users by ID](/users/search/v3/get-users-by-id-endpoint) and [Get Users by Email](/users/search/v3/get-users-by-email-endpoint). Searches using these endpoints will reflect the results of all successful write operations, including those that occurred shortly prior to your request.
+* Use a well-known schema for metadata:
+ * Use consistent data types for properties.
+ * Avoid dynamic property names.
+ * Avoid large schema sizes and deep structures.
+ * Avoid storing data you do not need for authentication and authorization purposes.
+* Search queries time out (HTTP status code 503) if they're not completed in two seconds or less. Queries that take longer indicate that it's either an expensive query or that the query has an error resulting in it not completing quickly
+* Don't use a search criteria that returns a large data set (more than 1000 results).
+* Don't use existence queries (for example, "give me all users with a property regardless of its value").
+* Don't poll the search APIs.
+* Don't use large metadata fields (try to keep metadata fields to 2 KB or less).
+* Using wildcard on searches can affect performance. In some cases, wildcard searches on large data sets can result in time out errors. We also recommend avoiding wildcards prefixed to the search term, while using them as suffixes yields better performance.
+* Escape the space character to improve performance (e.g., `q=name:John Doe` should be written as `q=name:John\ Doe`)
+* If you are using [user search engine v2](/api/management/v2/user-search), check out the section on [migrating from v2 to v3](/users/search/v3/migrate-search-v2-v3).
+
+::: note
+The user search engine v3 is not available in Management API v1, which is deprecated. If you are using the Management API v1, you will need to upgrade to [Management API v2](/api/management/v2) before being able to use the user search engine v3. See [Management API v1 vs v2](/api/management/v2/changes) for more information.
+:::
diff --git a/articles/best-practices/tenant-settings.md b/articles/best-practices/tenant-settings.md
new file mode 100644
index 0000000000..fd9e1a4528
--- /dev/null
+++ b/articles/best-practices/tenant-settings.md
@@ -0,0 +1,70 @@
+---
+title: Tenant Settings Best Practices
+description: Learn about recommended tenant settings in Auth0.
+topics:
+ - best-practices
+ - configuration
+ - settings
+ - tenant
+contentType:
+ - reference
+useCase:
+ - best-practices
+ - tenant
+ - tenant-settings
+---
+# Tenant Settings Best Practices
+
+Here are some best practices for configuring [tenants](/getting-started/the-basics#account-and-tenants).
+
+## Specify a production tenant
+
+Visit [Auth0 Support Center > Tenants](https://support.auth0.com/tenants/public) and specify your production tenant. Production tenants get higher rate limits than non-production tenants. On non-enterprise plans, only one tenant per subscription can be set as a production tenant.
+
+## Set up branding configuration
+
+Go to your [tenant's general settings](${manage_url}/#/tenant) and provide your branding information:
+
+- your application or company name
+- a URL to your logo image
+- your company's support email address
+- your company's support URL
+
+The support email address and URL is shown on the default error page, so users can contact your support if they have an issue. You can also [host your own custom error page](/universal-login/custom-error-pages) and configure Auth0 to use it instead. Using your own error page, you can provide more complete and customized explanations to users about what to do in the event of an error. Setting up your own custom error page is recommended, but not required.
+
+## Set up Custom Domain
+
+You can configure [custom domains](/custom-domains) in your tenant settings.
+
+If you want to use a custom domain name for the Universal Login [page](/universal-login), set up the custom domain at the start to minimize changes you’ll need to make later.
+
+For SAML connections that authenticate users against remote SAML Identity Providers, you should set up the custom domain before configuring any SAML providers as changing the domain across multiple SAML providers is challenging.
+
+## Set Single Sign-on session timeout
+
+The Single Sign-on (SSO) [session timeout value](/dashboard/reference/settings-tenant#login-session-management) in your tenant settings specifies the time until a user's session expires. By default the value is 7 days. During this time, users can access your Auth0-integrated applications without re-entering their credentials.
+
+Adjust this value to fit your application’s desired user experience and security requirements.
+
+For example, enterprise environments may choose 8 hours or shorter to ensure users authenticate at least once per shift. But for customer-facing environments, where long sessions are desirable for the user experience, the value might be set to much longer than 7 days.
+
+## Periodically review dashboard admins
+
+On a regular basis, review the list of [dashboard administrators](/dashboard/reference/settings-tenant#dashboard-admins) with access to your Auth0 tenant and make sure that:
+
+- each person has a legitimate need for admin access
+- admins are registered with a company account
+- former employees no longer have access
+- there's more than one dashboard admin
+
+For further protection, turn on multi-factor authentication (MFA) for your dashboard admins. If a Dashboard Admin is locked out and needs their MFA reset, another Dashboard Admin should open an Auth0 [support ticket](/support/tickets) on their behalf. Auth0 can reset MFA for that admin after a verification process.
+
+## Turn off Enable Application Connections
+
+In your [tenant's advanced settings](${manage_url}/#/tenant/advanced), turn off **Enable application connections**.
+
+If this setting is on, all configured connections are enabled for new applications you create, so users may be able to login to an application with an unintended connection. By having connections disabled by default, you can explicitly enable the connections appropriate for each application.
+
+## Turn on Anomaly Detection
+
+To protect against brute force attacks and breached passwords, [turn on and configure Auth0 Anomaly Detection](/anomaly-detection/guides/set-anomaly-detection-preferences).
diff --git a/articles/best-practices/testing.md b/articles/best-practices/testing.md
new file mode 100644
index 0000000000..a7801babdd
--- /dev/null
+++ b/articles/best-practices/testing.md
@@ -0,0 +1,85 @@
+---
+title: Testing Best Practices for Rules
+description: Learn about best practices for testing.
+topics:
+ - best-practices
+ - custom-database
+ - extensibility
+ - database-action-scripts
+ - custom-database-connections
+ - scripts
+ - rules
+contentType: reference
+useCase:
+ - best-practices
+ - custom-database
+ - database-action-scripts
+ - rules
+---
+
+# Testing Best Practices for Rules
+
+The Auth0 Dashboard provides the facility to [`TRY`](/rules/guides/debug) a rule for the purpose of testing and debugging. This facility allows a mock [`user`](/best-practices/rules#user-object) and [`context`](/best-practices/rules#context-object) object to be defined, which is then passed to the rule as part of its execution. The resulting output from the rule (including any console logging) is displayed upon completion. While this provides an immediate at-a-glance way to unit test a rule, it is very much a manual approach, and one which is unable to leverage the use of automated testing tools such as [Mocha](https://mochajs.org/) or [rewire](https://www.npmjs.com/package/rewire).
+
+::: panel Best Practice
+As a best practice, and as part of the recommended [support for the Software Development Life Cycle](https://auth0.com/docs/architecture-scenarios/implementation/b2c/b2c-architecture#sdlc-support), you should use a separate test Tenant in Auth0 to test any rule/rule changes before deploying to production.
+:::
+
+## Automation
+
+With the help of a little boilerplate, however, it is possible to implement in a way that enables a rule to be deployed and executed in an Auth0 Tenant *and*, without modification, to be consumed in any Continuous Integration/Continuous Deployment (CI/CD) automated (unit) testing environment:
+
+```js
+ const vm = require('vm');
+ const fs = require('fs');
+ var user = {
+ "name": "jdoe@foobar.com",
+ "email": "jdoe@foobar.com",
+ "user_id": "auth0|0123456789",
+ .
+ .
+ };
+ var context = {
+ "clientID": "123456789",
+ "clientName": "MyWebApp",
+ "connection": "MyDbConn",
+ "connectionStrategy": "auth0",
+ "protocol": "oidc-basic-profile",
+ .
+ .
+ };
+
+ global.configuration = {
+ DEBUG: true
+ };
+
+ vm.runInThisContext(
+ "(()=>{return " + fs.readFileSync('./rules/Normalized Profile Claims.js') + " })();", {
+ // filename for stack traces
+ filename: 'Normalized Profile Claims.js',
+ displayErrors: true
+ }
+ )(
+ user,
+ context,
+ function callback() {
+ console.log("Complete");
+ }
+ );
+```
+
+As shown in the example above, some relatively straightforward testing can be implemented (in an independent node module) by using the Node.js [VM](https://www.w3schools.com/nodejs/ref_vm.asp) to execute the rule to be tested. In this case, a rule named Normalized Profile Claims is read from a file, and some boilerplate is added around the rule (JavaScript) code prior to executing it (the boilerplate being in the strings that both prefix and suffix the filesystem call to [read the file](https://nodejs.org/api/fs.html#fs_fs_readfilesync_path_options) containing the rule code).
+
+::: note
+The options object passed on the call to `runInThisContext` provides information that can be used to assist with [debugging](/best-practices/debugging) in the case where any exceptional error condition(s) may arise. Please see the Node.js [documentation](https://node.readthedocs.io/en/stable/api/vm/) for further information regarding this function call.
+:::
+
+The first two objects passed to the rule during testing represent the [`user`](/best-practices/rules#user-object) and [`context`](/best-practices/rules#context-object) objects, and these can be mocked in a fashion similar to that employed in the Auth0 Dashboard `TRY` functionality. The [`callback`](/best-practices/rules#callback-function) function, supplied as the third parameter, can be implemented to simulate pipeline continuation, subsequently performing execution of the next rule in [order](/best-practices/rules#order).
+
+::: panel Best Practice
+The `callback` function supplied can be used to ensure execution of the callback is performed *at least* once by having the (callback) function complete the test and/or provide an assertion. We also recommend providing implementation to also ensure that multiple execution of the callback is not performed by a rule.
+:::
+
+In addition, the (Node.js) `global` object can be used to provide both the [configuration](/best-practices/rules#environment) object and also an instance of the [`auth0`](/best-practices/rules#auth0-object) object if required. In the sample above, a global `configuration` object has been defined that aligns with recommended practices to assist with [debugging](/best-practices/debugging) (as described in the section above).
+
+The sample above also makes use of the file system directory structure provided by Auth0 [Deploy CLI](/extensions/deploy-cli)—the tooling which can assist with rule [deployment](/best-practices/deployment).
diff --git a/articles/best-practices/token-best-practices.md b/articles/best-practices/token-best-practices.md
new file mode 100644
index 0000000000..0629c66681
--- /dev/null
+++ b/articles/best-practices/token-best-practices.md
@@ -0,0 +1,26 @@
+---
+description: Learn about the best practices when using tokens in authentication and authorization.
+topics:
+ - tokens
+ - jwt
+contentType:
+ - references
+useCase:
+ - invoke-api
+ - secure-api
+ - add-login
+---
+
+# Token Best Practices
+
+* **Keep it secret. Keep it safe.** The signing key should be treated like any other credential and revealed only to services that need it.
+
+* **Do not add sensitive data to the payload.** Tokens are signed to protect against manipulation and are easily decoded. Add the bare minimum number of claims to the payload for best performance and security.
+
+* **Give tokens an expiration.** Technically, once a token is signed, it is valid forever—unless the signing key is changed or expiration explicitly set. This could pose potential issues so have a strategy for expiring and/or revoking tokens.
+
+* **Embrace HTTPS.** Do not send tokens over non-HTTPS connections as those requests can be intercepted and tokens compromised.
+
+* **Consider all of your authorization use cases.** Adding a secondary token verification system that ensures tokens were generated from your server, for example, may not be common practice, but may be necessary to meet your requirements.
+
+* **Store and reuse.** Reduce unnecessary roundtrips that extend your application's attack surface, and optimize plan token limits (where applicable) by storing access tokens obtained from the authorization server. Rather than requesting a new token, use the stored token during future calls until it expires. How you store tokens will depend on the characteristics of your application: typical solutions include databases (for apps that need to perform API calls regardless of the presence of a session) and HTTP sessions (for apps that have an activity window limited to an interactive session). For an example of server-side storage and token reuse, see [Obtaining and Storing Access Tokens to Call External APIs](https://github.com/auth0/express-openid-connect/blob/master/EXAMPLES.md#4-obtaining-access-tokens-to-call-external-apis) in our Github repo.
diff --git a/articles/best-practices/user-data-storage-best-practices.md b/articles/best-practices/user-data-storage-best-practices.md
new file mode 100644
index 0000000000..d00a25c57e
--- /dev/null
+++ b/articles/best-practices/user-data-storage-best-practices.md
@@ -0,0 +1,28 @@
+---
+title: User Data Storage Best Practices
+description: Learn about recommendations for using Auth0 storage mechanisms.
+topics:
+ - users
+ - user-management
+ - user-profiles
+ - data-storage
+ - swift
+ - ios
+ - nodejs
+ - api
+contentType: reference
+useCase: manage-users
+---
+# User Data Storage Best Practices
+
+Auth0 stores user information for your tenant in a hosted cloud database, or you can choose to store user data in your own custom external database.
+
+## External database vs. Auth0 data store
+
+To store user data beyond the basic information Auth0 uses for authentication, you can use the Auth0 data store or a [custom database](/connections/database/mysql). However, if you use the additional data for authentication purposes, we recommend that you use the Auth0 data store, as this allows you to manage your user data through the [Auth0 Management Dashboard](${manage_url}).
+
+The Auth0 data store is customized for authentication data. Storing anything beyond the default user information should be done only in limited cases. Here's why:
+
+* **Scalability**: The Auth0 data store is limited in scalability, and your Application's data may exceed the appropriate limits. By using an external database, you keep your Auth0 data store simple, while the more efficient external database contains the extra data;
+* **Performance**: Your authentication data is likely accessed at lower frequencies than your other data. The Auth0 data store isn't optimized for high frequency use, so you should store data that needs to be retrieved more often elsewhere;
+* **Flexibility**: Because the Auth0 data store was built to accommodate only user profiles and their associated metadata, you are limited in terms of the actions you can perform on the database. By using separate databases for your other data, you can manage your data as appropriate.
diff --git a/articles/branding-customization/index.md b/articles/branding-customization/index.md
new file mode 100644
index 0000000000..78e6b2c950
--- /dev/null
+++ b/articles/branding-customization/index.md
@@ -0,0 +1,53 @@
+---
+classes: topic-page
+title: Brand and Customize
+description: Learn how to customize and apply branding to Auth0's product.
+topics:
+ - branding
+ - customization
+contentType: index
+useCase:
+ - customize-domains
+ - customize-emails
+ - localize
+ - customize-templates
+---
+
+
+
+
Brand and Customize
+
+ Learn how to customize and apply branding to Auth0's product.
+
+
+ Auth0 allows you to map the domain for your tenant to a custom domain of your choosing. This allows you to maintain a consistent experience for your users by keeping them on your domain instead of redirecting or using Auth0's domain.
+
+ Auth0 provide several types of emails including verification emails, welcome emails, change password emails, breached password emails, and blocked account emails. Learn how to customize these emails.
+
+ Multi-factor Authentication (MFA) is a method of verifying a user's identity by requiring them to present more than one piece of identifying information, such as a password, a mobile device, or a fingerprint. When mobile devices are selected, you can customize the SMS or Voice messages sent by Auth0 during enrollment and verification.
+
+ Auth0 supports methods of translating and internationalizing various features of our products. Learn how to set up translation and handling of multiple languages.
+
+
+
\ No newline at end of file
diff --git a/articles/cms/index.md b/articles/cms/index.md
index e93f5817e6..a213594235 100644
--- a/articles/cms/index.md
+++ b/articles/cms/index.md
@@ -1,20 +1,27 @@
---
url: /cms
description: Explains CMS Identity Plugins such as WordPress and Joomla.
+topics:
+ - wordpress
+ - joomla
+ - cms
+contentType: concept
+useCase:
+ - add-login
---
# CMS Identity Plugins
-Auth0 provides Content Management System Plugins/Extensions to integrate your CMS installation with your Auth0 account. These plugins enable Single Sign On for Enterprises, social login and user/password login through all your instances and platforms.
+Auth0 provides Content Management System Plugins/Extensions to integrate your CMS installation with your Auth0 account. These plugins enable Single Sign-on (SSO) for Enterprises, social login and user/password login through all your instances and platforms.
Login features are implemented through a new Login Widget (powered by Auth0) that enables:
-- Single Sign On with Enterprise Directories (LDAP, AD, Google Apps, Office365 and SAML Provider)
-- Shared User/Password between multiple WordPress accounts for Single Sign On
-- Single Sign On with over 30 [Social Providers](/identityproviders)
+- SSO with Enterprise Directories (LDAP, AD, G Suite, Office365 and SAML Provider)
+- Shared User/Password between multiple WordPress accounts for SSO
+- SSO with over 30 [Social Providers](/identityproviders)
- User Management Dashboard
- Optional Two Factor Authentication
-- Single Sign On between WordPress and other applications
+- SSO between WordPress and other applications
- Reporting and Analytics
diff --git a/articles/cms/joomla/configuration.md b/articles/cms/joomla/configuration.md
index e6a6cb2741..2219d97919 100644
--- a/articles/cms/joomla/configuration.md
+++ b/articles/cms/joomla/configuration.md
@@ -1,5 +1,11 @@
---
description: How to configure your Joomla instance for use with Auth0.
+topics:
+ - joomla
+ - cms
+contentType: how-to
+useCase:
+ - add-login
---
# Joomla Integration
@@ -14,7 +20,7 @@ To use Auth0 with Joomla, be sure you have a valid [Application](/applications).

-2. Provide the requested values for your Auth0 application. You can find the **Domain**, **Client ID**, and **Client Secret** values using the the [Application Settings page](${manage_url}/#/applications/${account.clientId}/settings). Click **Save & Close** to proceed.
+2. Provide the requested values for your Auth0 application. You can find the **Domain**, **Client ID**, and **Client Secret** values using the [Application Settings page](${manage_url}/#/applications/${account.clientId}/settings). Click **Save & Close** to proceed.

@@ -36,7 +42,7 @@ To use Auth0 with Joomla, be sure you have a valid [Application](/applications).

-4. Switch over the the **Menu Assignment** tab, and using the **Module Assignment** drop-down menu, select **On all pages**.
+4. Switch over the **Menu Assignment** tab, and using the **Module Assignment** drop-down menu, select **On all pages**.

@@ -66,5 +72,5 @@ You can configure your Auth0-Joomla Extension by adjusting the **Module** and **
| - | - |
| Translation | A valid JSON object representing the [Lock's `dict` parameter](/libraries/lock/customization#dict-string-object-). If set, this overrides the Title setting |
| Username style | Toggles whether the username should be a value selected by the user or their email address |
-| Remember last login | Requests SS0 data and [enables SSO](/libraries/lock/customization#rememberlastlogin-boolean-) |
+| Remember last login | Requests Single Sign-on (SSO) data and [enables SSO](/libraries/lock/customization#rememberlastlogin-boolean-) |
| Widget URL | The URL of the [latest Lock version](https://github.com/auth0/lock#install) |
diff --git a/articles/cms/joomla/installation.md b/articles/cms/joomla/installation.md
index 315c866036..5da40cf615 100644
--- a/articles/cms/joomla/installation.md
+++ b/articles/cms/joomla/installation.md
@@ -1,5 +1,11 @@
---
description: How to install Auth0 onto your Joomla platform.
+topics:
+ - joomla
+ - cms
+contentType: how-to
+useCase:
+ - add-login
---
# Joomla Installation
diff --git a/articles/cms/wordpress/configuration.md b/articles/cms/wordpress/configuration.md
index 53f59bc218..e8807a0561 100644
--- a/articles/cms/wordpress/configuration.md
+++ b/articles/cms/wordpress/configuration.md
@@ -1,249 +1,236 @@
---
description: How to configure WordPress as an application with Auth0.
+topics:
+ - wordpress
+ - cms
+contentType: how-to
+useCase:
+ - add-login
+ - build-an-app
+ - customize-connections
+ - secure-an-api
+ - manage-users
---
+# Configuring Login by Auth0
-# Configuration of the Login by Auth0 WordPress Plugin
+Login by Auth0 can be configured using the Setup Wizard in the plugin ([covered here](/cms/wordpress/installation#setup-wizard)) or manually for more control over the process. The instructions below can also be used if the Setup Wizard did not complete or as part of troubleshooting login issues.
-By default, new installations of Login by Auth0 run the Setup Wizard and ask for an app token and attempt to setup all necessary components within your Auth0 tenant. This includes:
-
-* Creating a new Application using your site name with the correct app type and URLs
-* Creating a database Connection for this Application for storing users
-* Creating an application grant for the system Auth0 Management API
-* Creating a new user for the WordPress administrator running the wizard
-
-Once this process is complete, your tenant is set up correctly and ready to accept signups and logins.
+::: note
+You will need to be logged into your Auth0 account before starting the steps below. If you don't have one yet, [create one here](https://auth0.com/signup).
+:::
-The Setup Wizard must run to completion for your site to be setup correctly. If the Wizard fails for any reason before the "setup successful" screen, check the plugin error log at **wp-admin > Auth0 > Error Log** and the steps below to determine the issue.
+## Auth0 configuration
-It can be helpful, if you're having any issues with logging in or creating accounts, to walk through the screens for each section below to confirm your setup.
+Your [Auth0 tenant](/getting-started/the-basics#account-and-tenants) must be configured to accept login requests from your WordPress site and source user identities from at least one [Connection](/identityproviders), whether that's an Auth0 database, a social connection, or a business directory.
-You'll need to be logged into your Auth0 account before starting the steps below. If you don't have one yet, [create one here](https://auth0.com/signup).
+### Application setup
-## Auth0 configuration
+1. First, we need an Application for your WordPress site:
-### Application setup
+ - **If you're troubleshooting the Setup Wizard**, navigate to the [Applications](${manage_url}/#/applications) screen and look for an Application that is similar to your WordPress site name. If you don't find one, it means that an Application was not created by the Wizard. Restart the Setup Wizard in WordPress or follow the step just below to create an Application manually.
+ - **If you're configuring manually**, navigate to the [Applications](${manage_url}/#/applications) screen and click **Create Application**. Enter a name for the Application, select **Regular Web Applications**, and click **Create**.
-First, we'll check for the Application created for your WordPress site.
+ 
-1. Navigate to the [Applications](${manage_url}/#/applications) page and look for an application that is similar to your site name. If you don't find one, it means that an Application was not created by the Wizard. Restart the Setup Wizard or create a new Application manually by clicking **Create Application**. Enter a name for the application, select **Regular Web Applications**, and click **Create**.
-
- 
+2. Click on the **Settings** tab for the Application. You will see your Domain, Client ID, and Client Secret, which are used in **wp-admin > Auth0 > Settings** to connect to Auth0.
-1. Click on the name to get to the **Settings** tab. You will see your Domain, Client ID, and Client Secret, which are used in **wp-admin > Auth0 > Settings** to make a connection to Auth0.
+ 
- 
+3. **Application Type** must be set to **Regular Web Application** and **Token Endpoint Authentication Method** must be set to **Post**
-1. **Application Type** must be set to **Regular Web Application**
+4. Scroll down to **Allowed Callback URLs** and provide the WordPress site URL with `?auth0=1` appended:
-1. Scroll down to **Allowed Callback URLs** and input your WordPress site's homepage URL, login URL, and index.php URL with `?auth0=1` appended to it, separated by a comma. It should look like this:
+```
+https://your-wordpress-domain.com/index.php?auth0=1
+```
- 
+::: warning
+The Callback URL here **must not** be cached, or you might see an "Invalid state" error during login. Please see [these troubleshooting steps](/cms/wordpress/invalid-state#cached-callback-urls) for more information.
+:::
-1. Enter your WordPress site's home domain (where the WordPress site appears) and, if different, site domain (where wp-admin is served from) in the **Allowed Web Origins** field
+5. Enter your WordPress site's **WordPress Address (URL)** (where the WordPress site appears publicly) and, if different, the **Site Address (URL)** (where wp-admin is served from) in the **Allowed Web Origins** field. Both of these values are found on your WordPress site's general settings screen.
-1. Enter your WordPress site's login URL in the **Allowed Logout URLs** field
+6. Enter your WordPress site's login URL in the **Allowed Logout URLs** field
-1. Leave the **Allowed Origins (CORS)** field blank (it will use the **Allowed Callback URLs** values from above)
+7. Leave the **Allowed Origins (CORS)** field blank (it will use the **Allowed Callback URLs** values from above)
- ::: note
- Make sure to match your site's protocol (http or https) and use the site URL as a base, found in **wp-admin > Settings > General > WordPress Address (URL)** for all URL fields above.
- :::
+::: note
+Make sure to match your site's protocol (http or https) and use the home URL as a base, found in **wp-admin > Settings > General > WordPress Address (URL)** for all URL fields above.
+:::
-1. Scroll down and click the **Show Advanced Settings** link, then the **OAuth** tab and make sure **JsonWebToken Signature Algorithm** is set to RS256. If this needs to be changed later, it should be changed here as well as in wp-admin (see Settings > Basic below).
+8. Scroll down and click the **Show Advanced Settings** link, then the **OAuth** tab and make sure **JsonWebToken Signature Algorithm** is set to RS256. If this needs to be changed later, it should be changed here as well as in wp-admin (see Settings > Basic below).
-1. Turn off **OIDC Conformant**.
+9. Turn on **OIDC Conformant**.
- 
+ 
-1. Click the **Grant Types** tab and select at least **Implicit,** **Authorization Code,** **Refresh Token,** and
-**Client Credentials**.
+10. Click the **Grant Types** tab and select at least **Authorization Code** and **Client Credentials**.

-1. Click **Save Changes** if anything was modified.
+11. Click **Save Changes**.
### Authorize the Application for the Management API
-In order for your WordPress site to perform certain actions on behalf of your Auth0 tenant, you'll need to authorize the Application created above to access the Management API.
+In order for your WordPress site to perform certain actions on behalf of your Auth0 tenant, you'll need to authorize the Application created above to access the Management API. This is not required but will enable retrieving complete user data on login (including `user_metadata` and `app_metadata`), email and password changes for users, and email verification re-sending when verified emails are required.
-1. Navigate to the [APIs](${manage_url}/#/apis) page
+1. Make sure your Application allows the Client Credentials grant (step 10 in the section above).
-1. Click on **Auth0 Management API**, then the **Machine to Machine Applications** tab
+2. Navigate to the [APIs](${manage_url}/#/apis) page.
-1. Look for the Application you created above and click **Unauthorized** to grant access
+3. Click on **Auth0 Management API**, then the **Machine to Machine Applications** tab.
-1. In the panel that appears, select the following scopes below and click **Update** (you can search using the **Filter scopes** field)
+4. Look for the WordPress Application and click **Unauthorized** to grant access.
- * `create:clients`
- * `update:clients`
- * `update:connections`
- * `create:connections`
- * `read:connections`
- * `create:rules`
- * `delete:rules`
- * `read:users`
- * `update:users`
- * `create:users`
- * `update:guardian_factors`
+5. In the panel that appears, select only the `read:users` and `update:users` scopes and click **Update** (you can search using the **Filter scopes** field).
-
+
### Database Connection setup
-Database Connections enable the typical username and password login seen on most sites. This type of Connection is
-not required and can be skipped if you're using passwordless or social logins only.
-
-1. If you used the wizard during setup, navigate to the [Connections > Database](${manage_url}/#/connections/database) page and look for a Connection that has a similar name to the Application setup above. Otherwise, you can create a new
-Connection, use an existing Connection, or use the default **Username-Password-Authentication**. Click an existing Connection name to view settings or click **Create DB Connection** and follow the steps.
+Database Connections enable username and password login with user records stored at Auth0. This type of Connection is not required and can be skipped if you're using passwordless, social, or enterprise logins only.
- 
+1. If you used the wizard during setup, navigate to the [Connections > Database](${manage_url}/#/connections/database) page and look for a Connection that has a similar name to the Application setup above. Otherwise, you can create a new Connection, use an existing Connection, or use the default **Username-Password-Authentication**. Click an existing Connection name to view settings or click **Create DB Connection** and follow the steps.
-1. Click the **Settings** tab, set **Password Strength** to the same as your wp-admin setting (default is Fair), and click **Save** at the bottom. If you want your password policy to be stronger or weaker, make sure to set it both here and at **wp-admin > Auth0 > Settings**.
+ 
-1. Now click the **Applications** tab and activate the Application created above.
+1. Click the **Applications** tab and activate the Application created above.
- 
+ 
### Social Connection setup
-See our [dedicated page on Social Connections](/identityproviders#social) for detailed information on how to activate and configure these login methods.
+See [Social Connections](/connections/identity-providers-social) for detailed information on how to activate and configure this login method.
-### Update Auth0 settings in WordPress
+### Enterprise Connection setup
-1. Go to back to the [Applications](${manage_url}/#/applications) page and select the Application created above.
+See [Enterprise Connections](/connections/identity-providers-enterprise) for detailed information on how to activate and configure this login method.
- 
+## WordPress Configuration
-1. In a new tab/window, log into wp-admin for your WordPress site and go to **wp-admin > Auth0 > Settings**.
+1. Go to back to the [Applications](${manage_url}/#/applications) page and select the Application created above.
-1. Click on the **Basic** tab.
+1. In a new tab/window, log into wp-admin for your WordPress site and go to **wp-admin > Auth0 > Settings**.
1. Copy **Domain**, **Client ID**, and **Client Secret** from your Auth0 Application page to your WordPress settings using the Copy to Clipboard buttons next to each field.
-1. Make sure **Application Signing Algorithm** matches the Application's Advanced > OAuth setting.
-
1. Scroll down and click **Save Changes**.
-## Plugin settings
+## PHP Constant Setting Storage
-### Basic
+Plugin settings can be saved to the database (default) or they can be set using a specifically named PHP constant. This will allow for sensitive data like the client secret, API token, and migration token to be stored more securely (assuming that file they are defined in is [stored securely](https://codex.wordpress.org/Hardening_WordPress)).
-* **Domain:** The app Domain copied from the Application settings in your dashboard.
+The constant **must** be defined before the plugin is loaded or it will not be used. This should happen in your `wp-config.php` file or in a [must-use plugin](https://codex.wordpress.org/Must_Use_Plugins). If the constant is defined in your theme's `functions.php` or in a plugin that loads after Auth0, the value will be ignored.
-* **Client ID:** The app Client ID copied from the Application settings in your dashboard.
+The PHP constants are defined like so:
-* **Client Secret:** The app Client Secret copied from the Application settings in your dashboard.
+```php
+// Storing the client secret in a constant.
+// Add to wp-config.php or anywhere before WP_Auth0_Options_Generic is instantiated.
+// Constant name is "AUTH0_ENV_" + option key in caps.
+define( 'AUTH0_ENV_CLIENT_SECRET', 'YOUR_CLIENT_SECRET_HERE' );
+```
-* **Client Secret Base64 Encoded:** Whether or not the Client Secret is Base64 encoded; it will say below the Client Secret field in your Auth0 dashboard whether or not this should be turned on.
+The default constant name should be `AUTH0_ENV_` followed by the option name to override in all caps (the prefix can be modified with the `auth0_settings_constant_prefix` filter [explained here](/cms/wordpress/extending#auth0_settings_constant_prefix)). All plugin options that can be overridden and their keys can be found in the `WP_Auth0_Options::defaults()` [method](https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_Lock_Options.php).
-* **Application Signing Algorithm:** The algorithm used for signing tokens from the Advanced Application Settings, OAuth tab; default is RS256.
+**Note:** The `migration_token` value is generated by the plugin when user migration is turned on. If there is already a value in the admin, make sure to set the constant to the same value. If that value needs to change, it also must be changed in the custom scripts for the database Connection being used in the Auth0 dashboard.
-* **Cache Time (minutes):** How long the JWKS information should be stored.
+The settings field will change its display based on this new value and show the constant being used for reference. This value will be used everywhere in the plugin automatically.
-* **API token:** The token required to allow the plugin to communicate with Auth0 to update your tenant settings. If the token has been set, this field will display "Not Visible". If blank, no token has been provided and you will have to [generate a token](/api/management/v2/tokens#get-a-token-manually) with the appropriate scopes listed here.
+**Important:** Saving the settings page after setting a constant value will validate the constant-set values (but not change them) and delete them from the options array being saved to the database. If you are just testing this functionality, do not save settings in the WordPress admin page until you're ready to delete that value.
-* **WordPress login enabled:** If enabled, displays a link on the login page to access the regular WordPress login.
+All sites in a WordPress multi-site network will use the same constant value making this an easy way to setup a network using a single Application and database Connection.
-* **Allow signup:** User signup will be available only if the WordPress *Anyone can register* option is enabled. You can find this setting under **Settings > General > Membership**.
+## Plugin settings
-### Features
+### Basic
-* **Password Policy:** Select the level of complexity you want to enforce for user passwords. For more information on password policies, see [Password Strength in Auth0 Database Connections](/password-strength).
+* **Domain:** The Domain copied from the Application settings in your dashboard. Option name is `domain`.
-* **Single Sign On (SSO):** Enables SSO on your WordPress, allowing users to log in once and be automatically logged into any of your sites which use Auth0. For more information, see [What is SSO?](/sso).
+* **Custom Domain:** The Custom Domain for your tenant, if one is configured. See [Custom Domains](/custom-domains) for more information. Option name is `custom_domain`.
-* **Single Logout:** Enable this option for Single Logout. For more information, see [What is Single Log Out?](/sso/single-sign-on#what-is-single-log-out-).
+* **Client ID:** The Client ID copied from the Application settings in your dashboard. Option name is `client_id`.
-* **Multifactor Authentication (MFA):** Enable this option for multifactor authentication with Google Authenticator. (See [Multifactor Authentication in Auth0](/multifactor-authentication) for more information). You can enable other MFA providers on the [Auth0 dashboard](${manage_url}/#/multifactor).
+* **Client Secret:** The Client Secret copied from the Application settings in your dashboard. Option name is `client_secret`.
-* **FullContact integration:** Enable this option to fill your user profiles with the data provided by FullContact. A valid API key is required. For more information, see [Augment User Profile with FullContact](/scenarios/mixpanel-fullcontact-salesforce#2-augment-user-profile-with-fullcontact-).
+* **JWT Signature Algorithm** The algorithm used for signing tokens from the Advanced Application Settings, OAuth tab; default is RS256. Option name is `client_signing_algorithm`.
-* **Store geolocation:** Enable this option to store geolocation information based on the IP addresses saved in `user_metadata`.
+* **JWKS Cache Time (in minutes):** How long the JWKS information should be stored when using the RS256 JWT Signature Algorithm. Option name is `cache_expiration`.
-* **Store zip-code income:** Enable this option to store income data based on the ZIP code calculated from each user's IP address.
+* **Original Login Form on wp-login.php:** Provides ways to access or block the core WordPress login page. Option name is `wordpress_login_enabled`. Login page code option name is `wle_code`.
-* **Override WordPress avatars:** Forces WordPress to use Auth0 avatars .
+ * **Never** will not allow the core WordPress login form to display.
+ * **Via a link under the Auth0 form** will display a link to the WordPress core login form directly below the Auth0 embedded one on `wp-login.php`. The login page can also be accessed directly by adding `?wle` to the login URL.
+ * **When "wle" query parameter is present** will allow the login page to be accessed directly by adding `?wle` to the login URL. This will bypass the Universal Login Page redirect.
+ * **When "wle" query parameter contains specific code** will allow the login page to be accessed directly by adding `?wle=` plus a code to the login URL. The code is generated automatically and will be shown below the controls for this setting. This will bypass the Universal Login Page redirect.
-### Appearance
+* **Allow Signups:** User signup will be available only if the WordPress *Anyone can register* option is enabled. You can find this setting under **Settings > General > Membership**.
-* **Icon URL:** Sets the Lock display icon.
+### Features
-* **Form Title:** Sets the title of the Lock widget.
+* **Universal Login Page:** Redirects the `wp-login.php` page to the Universal Login Page for Single Sign-on (SSO) authentication using all active Connections for this Application. Option name is `auto_login`.
-* **Big Social Buttons:** Toggles the social buttons size between big and small.
+* **Auto Login Method:** A single, active connection to use for authentication when **Universal Login Page** is turned on. Leave this blank to show all active Connections on the Universal Login Page. Option name is `auto_login_method`.
-* **Enable Gravatar Integration:** When user enters their email, their associated Gravatar picture is displayed in the Lock header.
+* **Auth0 Logout:** Enable this option to log out of Auth0 when logging out of WordPress. Option name is `singlelogout`.
-* **Login Form CSS:** Valid CSS that will be applied to the login page. For more information on customizing Lock, see [Can I customize the Login Widget?](https://github.com/auth0/wp-auth0#can-i-customize-the-login-widget).
+* **Override WordPress Avatars:** Forces WordPress to use Auth0 avatars. Option name is `override_wp_avatars`.
-* **Login Form JS:** Valid JS that will be applied to the login page. For more information on customizing Lock, see [Can I customize the Login Widget?](https://github.com/auth0/wp-auth0#can-i-customize-the-login-widget).
+### Embedded
-* **Login Name Style:** Selecting **Email** will require users to enter their email address to login. Set this to **Username** if you do not want to force a username to be a valid email address.
+Options here do not affect the Universal Login Page (see [this page](/universal-login) for customization options).
-* **Primary Color:** Information on this setting is [here](/libraries/lock/v11/configuration#primarycolor-string-).
+* **Passwordless Login:** Enable this option to turn on Passwordless login on all embedded Auth0 login forms. Passwordless connections are managed in the Auth0 dashboard and at least one must be active and enabled on this Application for this to work. Option name is `passwordless_enabled`.
-* **Language:** Information on this setting is [here](/libraries/lock/v11/configuration#language-string-).
+* **Icon URL:** Sets the icon above the embedded Auth0 login form. Option name is `icon_url`.
-* **Language Dictionary:** Information on this setting is [here](/libraries/lock/v11/configuration#languagedictionary-object-).
+* **Form Title:** Sets the title of the embedded Auth0 login form. Option name is `form_title`.
-### Advanced
+* **Enable Gravatar Integration:** When user enters their email, their associated Gravatar picture is displayed in the embedded Auth0 login form. Option name is `gravatar`.
-* **Require Verified Email:** If set, requires the user to have a verified email to log in. This can prevent some
-social Connections from working properly.
+* **Login Name Style:** Selecting **Email** will require users to enter their email address to login. Set this to **Username** if you do not want to force a username to be a valid email address. Option name is `username_style`. Option name is `client_secret_b64_encoded`.
-* **Remember User Session:** By default, user sessions live for two days. Enable this setting to keep user sessions live for 14 days.
+* **Primary Color:** Information on this setting is [here](/libraries/lock/v11/configuration#primarycolor-string-). Option name is `primary_color`.
-* **Login Redirection URL:** If set, redirects users to the specified URL after login. This does not affect logging in via the `[auth0]` shortcode. To change the redirect for the shortcode, add a `redirect_to` attribute, like so:
-
- `[auth0 redirect_to="http://yourdomain.com/redirect-here"]`
-
-* **Passwordless Login:** Enable this option to replace the login widget with Lock Passwordless.
+* **Extra Settings:** A valid JSON object that includes options to call Lock with. This overrides all other options set above. For a list of available options, see [Lock: User configurable options](/libraries/lock/customization) (e.g.: `{"disableResetAction": true }`). Option name is `extra_conf`.
-* **Force HTTPS callback:** Enable this option if your site allows HTTPS but does enforce it. This will force Auth0 callbacks to HTTPS in the case where your home URL is not set to HTTPS.
+* **Use Custom Lock JS URL:** When turned off, WordPress will use the latest tested version of Lock (Auth0 embedded login form) automatically. When turned on, administrators can provide a custom Lock URL to use. Option name is `custom_cdn_url`.
-* **Lock JS CDN URL:** The URL of to the latest available Lock widget in the CDN.
+* **Custom Lock JS URL:** A valid URL pointing to a version of Lock. This field will be automatically hidden when **Use Custom Lock JS URL** is turned off. Option name is `cdn_url`.
-* **Connections to Show:** List here each of the identity providers you want to allow users to login with. If left blank, all enabled providers will be allowed. (See [connections {Array}](/libraries/lock/customization#connections-array-) for more information.)
+* **Connections to Show:** List here each of the identity providers you want to allow users to login with. If left blank, all enabled providers will be allowed. (See [connections {Array}](/libraries/lock/customization#connections-array-) for more information.) Option name is `lock_connections`.
::: note
If you have enabled Passwordless login, you must list here all allowed social identity providers. (See [.social(options, callback)](https://github.com/auth0/lock-passwordless#socialoptions-callback) for more information.)
:::
-* **Link users with same email:** This option enables the linking of accounts with the same verified e-mail address.
-
-* **Auto provisioning:** Should new users from Auth0 be stored in the WordPress database if new registrations are not allowed? This will create WordPress users that do no exist when they log in via Auth0 (for example, if a user is created in the Auth0 dashboard).
-
- ::: note
- If registrations are allowed in WordPress, new users will be created regardless of this setting.
- :::
-
-* **User Migration:** Enabling this option will expose the Auth0 migration web services. However, the Connection will need to be manually configured in the [Auth0 dashboard](${manage_url}). For more information on the migration process, see [Import users to Auth0](/connections/database/migrating).
-
-* **Migration IPs whitelist:** Only requests from listed IPs will be allowed access to the migration webservice.
+### Advanced
-* **Auto Login (no widget):** Skips the login page (a single login provider must be selected).
+* **Require Verified Email:** If set, requires the user to have a verified email to log in. This can prevent some Connections from working properly if they do not provide an email address or an `email_verified` flag in the user profile data. Option name is `requires_verified_email`.
-* **Implicit Login Flow:** If enabled, uses the [Implicit Flow](/protocols#oauth-for-native-applications-and-javascript-in-the-browser) protocol for authorization in cases where the server is without internet access or behind a firewall.
+* **Skip Strategies:** If Require Verified Email is turned on, this setting will display. This field accepts strategy names to skip the verified email requirement on login and account association. This should **only** be used for strategies that do not provide an `email_verified` flag.
-* **Enable IP Ranges:** Select to enable the Auth0 plugin only for the IP ranges you specify in the **IP Ranges** textbox.
+* **Remember User Session:** By default, user sessions live for two days. Enable this setting to keep user sessions live for 14 days. Option name is `remember_users_session`.
-* **IP Ranges:** Enter one range per line. Range format should be: `xx.xx.xx.xx - yy.yy.yy.y`.
+* **Login Redirection URL:** If set, redirects users to the specified URL after login. This does not affect logging in via the `[auth0]` shortcode. Option name is `default_login_redirection`. To change the redirect for the shortcode, add a `redirect_to` attribute, like so:
-* **Valid Proxy IP:** List the IP address of your proxy or load balancer to enable IP checks for logins and migration web services.
+ `[auth0 redirect_to="http://yourdomain.com/redirect-here"]`
-* **Custom signup fields:** This field is the Json that describes the custom signup fields for lock. It should be a valid json and allows the use of functions (for validation). [More info here](/libraries/lock/v10/new-features#custom-sign-up-fields).
+* **Force HTTPS Callback:** Enable this option if your site allows HTTPS but does enforce it. This will force Auth0 callbacks to HTTPS in the case where your home URL is not set to HTTPS. Option name is `force_https_callback`.
-* **Extra settings:** A valid JSON object that includes options to call Lock with. This overrides all other options set above. For a list of available options, see [Lock: User configurable options](/libraries/lock/customization) (e.g.: `{"disableResetAction": true }`).
+* **Auto Provisioning:** Should new users from Auth0 be stored in the WordPress database if new registrations are not allowed? This will create WordPress users that do no exist when they log in via Auth0 (for example, if a user is created in the Auth0 dashboard). Option name is `auto_provisioning`.
-* **Extra settings:** A valid JSON object that includes options to call Lock with. This overrides all other options set above. For a list of available options, see [Lock: User configurable options](/libraries/lock/customization) (such as: `{"disableResetAction": true }`).
+ ::: note
+ If registrations are allowed in WordPress, new users will be created regardless of this setting.
+ :::
-* **Twitter consumer key and consumer secret:** The credentials from your Twitter app. For instructions on creating an app on Twitter, see [Obtain Consumer and Secret Keys for Twitter](/connections/social/twitter).
+* **User Migration:** Enabling this option will expose the Auth0 migration web services. However, the Connection will need to be manually configured in the [Auth0 dashboard](${manage_url}). For more information on the migration process, see our [documentation page on user migrations](/cms/wordpress/user-migration). The **Generate New Migration Token** button can be used to replace the saved token with a new one. Make sure to have your database Connection configuration page open to the **Custom Database** tab so you can replace the existing token with the new one in both scripts. Option name is `migration_ws`. Migration token option name is `migration_token`.
-* **Facebook app key and app secret:** The credentials from your Facebook app. For instructions on creating an app on Facebook, see [Obtain an App ID and App Secret for Facebook](/connections/social/facebook).
+* **Migration IPs Whitelist:** Only requests from listed IPs will be allowed access to the migration webservice. Option name is `migration_ips_filter`.
-* **Auth0 server domain:** The Auth0 domain, it is used by the setup wizard to fetch your account information.
+* **Valid Proxy IP:** List the IP address of your proxy or load balancer to enable IP checks for logins and migration web services. Option name is `valid_proxy_ip`.
-* **Anonymous data:** The plugin tracks anonymous usage data by default. Click to disable.
+* **Auth0 Server Domain:** The Auth0 domain, it is used by the setup wizard to fetch your account information. Option name is `auth0_server_domain`.
## Keep Reading
@@ -252,7 +239,6 @@ More information on the Login by Auth0 WordPress plugin:
::: next-steps
* [How does it work?](/cms/wordpress/how-does-it-work)
* [Install the plugin](/cms/wordpress/installation)
-* [JWT API authentication](/cms/wordpress/jwt-authentication)
* [Troubleshooting](/cms/wordpress/troubleshoot)
* [Extend the plugin](/cms/wordpress/extending)
:::
diff --git a/articles/cms/wordpress/extending.md b/articles/cms/wordpress/extending.md
index 434bb42a07..a2dc98c9f6 100644
--- a/articles/cms/wordpress/extending.md
+++ b/articles/cms/wordpress/extending.md
@@ -1,225 +1,622 @@
---
-description: How to extend the Login by Auth0 WordPress Plugin with hooks, filters, and functions.
+title: Extending the Login by Auth0 WordPress Plugin
+description: Learn how to extend the Login by Auth0 WordPress Plugin with hooks, filters, and functions.
toc: true
+topics:
+ - wordpress
+ - cms
+contentType:
+ - how-to
+useCase:
+ - add-login
+ - build-an-app
+ - customize-connections
---
+# Extending Login by Auth0
-# Extending the Login by Auth0 WordPress Plugin
-
-WordPress plugins can be extended to fit your specific requirements by using actions and filters to run custom code at specific points during runtime. This document outlines the existing hooks in the Login by Auth0 plugin. We're happy to review and approve new filters and actions that help you integrate even further in this plugin. Please
- see the Contributing section on the [GitHub repo readme for this plugin](https://github.com/auth0/wp-auth0/blob/master/README.md).
+WordPress plugins can be extended to fit your specific requirements by using actions and filters to run custom code at specific points during runtime. This document outlines the existing hooks in the Login by Auth0 plugin. We're happy to review and approve new filters and actions that help you integrate even further in this plugin. Please see the Contributing section on the [GitHub repo readme for this plugin](https://github.com/auth0/wp-auth0/blob/master/README.md).
## Actions
-Actions in WordPress run custom code at specific points during processing. [Learn more about actions here](https://developer.wordpress.org/plugins/hooks/actions/).
+Actions in WordPress run custom code at specific points during processing. [Learn more about actions here](https://developer.wordpress.org/plugins/hooks/actions/). These examples are maintained [here](https://github.com/joshcanhelp/auth0-wp-test/blob/master/inc/hooks-core-actions.php).
### auth0_before_login
This action runs in `WP_Auth0_LoginManager` after a user has been authenticated successfully but before they have been logged into WordPress. It can be used to stop the login process if needed using `wp_die()` or throwing an exception.
-**Example:**
-
```php
/**
- * @param WP_User $user - WordPress user ID
+ * Stop login process before logging in and output the current $user object.
+ * NOTE: The example below will break the user login process.
+ *
+ * @see WP_Auth0_LoginManager::do_login()
+ *
+ * @param WP_User $user - WordPress user object.
*/
-function a0_docs_ex_auth0_before_login ( $user ) {
- // ... do something before logging in
+function auth0_docs_hook_auth0_before_login( $user ) {
+ echo 'WP user:
' . print_r( $user, true ) . '
';
+ wp_die( 'Login process started!' );
}
-add_action( 'auth0_before_login', 'a0_docs_ex_auth0_before_login' );
-```
-
-### auth0_user_login
+add_action( 'auth0_before_login', 'auth0_docs_hook_auth0_before_login', 10, 1 );
+```
-This action runs in `WP_Auth0_LoginManager` after a user has been authenticated successfully and logged into
-WordPress. It can be used to set specific meta values, send notifications, or ping other services.
+### auth0_user_login
-**Example:**
+This action runs in `WP_Auth0_LoginManager` after a user has been authenticated successfully and logged into WordPress. It can be used to set specific meta values, send notifications, or ping other services.
```php
/**
- * @param integer $user_id - WordPress user ID
- * @param stdClass $userinfo - user information object from Auth0
- * @param boolean $is_new - true if the user was created in WordPress, false if not
- * @param string $id_token - ID token for the user from Auth0 (not used in code flow)
- * @param string $access_token - bearer access token from Auth0 (not used in implicit flow)
+ * Stop the login process after WP login.
+ * NOTE: The example below will break the user login process.
+ *
+ * @see WP_Auth0_LoginManager::do_login()
+ *
+ * @param integer $user_id - WordPress user ID for logged-in user
+ * @param stdClass $userinfo - user information object from Auth0
+ * @param boolean $is_new - true if the user was created in WordPress, false if not
+ * @param string $id_token - ID Token for the user from Auth0
+ * @param string $access_token - Bearer Access Token from Auth0 (not used in implicit flow)
+ * @param string $refresh_token - Refresh Token from Auth0 (not used in implicit flow)
*/
-function a0_docs_ex_auth0_user_login ( $user_id, $userinfo, $is_new, $id_token, $access_token ) {
- // ... do something after logging in
+function auth0_docs_hook_auth0_user_login( $user_id, $userinfo, $is_new, $id_token, $access_token, $refresh_token ) {
+ echo 'WP user ID: ' . $user_id . '';
+ echo 'Auth0 user info:
' . print_r( $userinfo, true ) . '
';
+ echo 'Added to WP DB?: ' . ( $is_new ? 'yep' : 'nope' ) . '';
+ echo 'ID Token: ' . ( $id_token ? $id_token : 'not provided' ) . '';
+ echo 'Access Token: ' . ( $access_token ? $access_token : 'not provided' ) . '';
+ echo 'Refresh Token: ' . ( $refresh_token ? $refresh_token : 'not provided' ) . '';
+ wp_die( 'Login successful! Home' );
}
-add_action( 'auth0_user_login', 'a0_docs_ex_auth0_user_login', 10, 5 );
-```
-
-### wpa0_user_created
+add_action( 'auth0_user_login', 'auth0_docs_hook_auth0_user_login', 10, 6 );
+```
-This action runs in `WP_Auth0_Users` just after a WordPress user is successfully created. It can be used to change
-user values, set additional user metas, or trigger other new user actions.
+### wpa0_user_created
-**Example:**
+This action runs in `WP_Auth0_Users` just after a WordPress user is successfully created. It can be used to change user values, set additional user metas, or trigger other new user actions.
```php
/**
- * @param integer $user_id - WordPress user ID for created user
- * @param string $email - email address for created user
- * @param string $password - password used for created user
- * @param string $f_name - first name for created user
- * @param string $l_name - last name for created user
+ * Stop the login process after a new user has been created.
+ * NOTE: The example below will break the user login process.
+ *
+ * @see WP_Auth0_Users::create_user()
+ *
+ * @param integer $user_id - WordPress user ID for created user
+ * @param string $email - email address for created user
+ * @param string $password - password used for created user
+ * @param string $f_name - first name for created user
+ * @param string $l_name - last name for created user
*/
-function a0_docs_ex_wpa0_user_created ( $user_id, $email, $password, $f_name, $l_name ) {
- // ... do something once a user has been created
+function auth0_docs_hook_wpa0_user_created( $user_id, $email, $password, $f_name, $l_name ) {
+ echo 'User ID: ' . $user_id . '';
+ echo 'Email: ' . $email . '';
+ echo 'Password: ' . $password . '';
+ echo 'First name: ' . $f_name . '';
+ echo 'Last name: ' . $l_name . '';
+ wp_die( 'User created!' );
}
-
-add_action( 'wpa0_user_created', 'a0_docs_ex_wpa0_user_created', 10, 5 );
+add_action( 'wpa0_user_created', 'auth0_docs_hook_wpa0_user_created', 10, 5 );
```
## Filters
-Filters in WordPress also run custom code at specific points during processing but always return a modified value of the same type that was passed in. [Learn more about filters here](https://developer.wordpress.org/plugins/hooks/filters/).
+Filters in WordPress also run custom code at specific points during processing but always return a modified value of the same type that was passed in. [Learn more about filters here](https://developer.wordpress.org/plugins/hooks/filters/). These examples are maintained [here](https://github.com/joshcanhelp/auth0-wp-test/blob/master/inc/hooks-core-filters.php).
### auth0_get_wp_user
-This filter is called after the plugin finds the related user to login (based on the auth0 `user_id`) and is used to override the default behaviour with custom matching rules (for example, always match by email).
+This filter is called after the plugin finds the related user to login (based on the auth0 `user_id`) and is used to override the default behavior with custom matching rules (for example, always match by email).
If the filter returns null, it will lookup by email as described in the [How does it work?](/cms/wordpress/how-does-it-work) document.
-**Example:**
-
```php
/**
- * @param WP_User|null $user - found WordPress user, null if no user was found
- * @param stdClass $userinfo - user information from Auth0
+ * Filter the WordPress user found during login.
+ *
+ * @see WP_Auth0_LoginManager::login_user()
+ *
+ * @param WP_User|null $user - found WordPress user, null if no user was found.
+ * @param stdClass $userinfo - user information from Auth0.
*
* @return WP_User|null
*/
-function auth0_theme_hook_auth0_get_wp_user( $user, $userinfo ) {
- // ... try to match another way, decide to replace $user
+function auth0_docs_hook_auth0_get_wp_user( ?WP_User $user, stdClass $userinfo ) {
+ $found_user = get_user_by( 'email', $userinfo->email );
+ $user = $found_user instanceof WP_User ? $user : null;
return $user;
}
-add_filter( 'auth0_get_wp_user', 'auth0_theme_hook_auth0_get_wp_user', 1, 2 );
+add_filter( 'auth0_get_wp_user', 'auth0_docs_hook_auth0_get_wp_user', 1, 2 );
```
### auth0_verify_email_page
-This filter runs in `WP_Auth0_Email_Verification` to change the HTML rendered when a user who is logging in needs to verify their email before gaining access to the site. Note that this HTML is passed to `wp_die()` where it is modified before being displayed (see the `_default_wp_die_handler()` definition in core for more information).
-
-**Example:**
+This filter runs in `WP_Auth0_Email_Verification` to change the HTML rendered when a user who is logging in needs to verify their email before gaining access to the site. Note that this HTML is passed to `wp_die()` where it is modified before being displayed (see the `_default_wp_die_handler()` definition in core for more information).
```php
/**
- * @param string $html - HTML to modify, echoed out within wp_die()
- * @param stdClass $userinfo - user info object from Auth0
- * @param string $id_token - DEPRECATED, do not use
+ * Filter the HTML used on the email verification wp_die page.
+ *
+ * @see WP_Auth0_Email_Verification::render_die()
+ *
+ * @param string $html - HTML to modify, echoed out within wp_die().
+ * @param stdClass $userinfo - user info object from Auth0.
*
* @return string
*/
-function a0_docs_ex_auth0_verify_email_page ( $html, $userinfo, $id_token ) {
- // ... modify $html by replacing or concatenating
+function auth0_docs_hook_auth0_verify_email_page( string $html, stdClass $userinfo ) {
+ $html = 'Hi ' . $userinfo->email . '! ' . $html;
+ $html = str_replace( 'email', 'banana', $html );
return $html;
}
-add_filter( 'auth0_verify_email_page', 'a0_docs_ex_auth0_verify_email_page', 10, 3 );
+add_filter( 'auth0_verify_email_page', 'auth0_docs_hook_auth0_verify_email_page', 10 );
```
### auth0_get_auto_login_connection
-This filter is used in `WP_Auth0_LoginManager` to modify what connection is used for the auto-login process. The
-setting in wp-admin is pulled and then passed through this filter.
-
-**Example:**
+This filter is used in `WP_Auth0_LoginManager` to modify what connection is used for the auto-login process. The setting in wp-admin is pulled and then passed through this filter.
```php
/**
- * @param string $connection - name of the connection, initially pulled from Auth0 plugin settings
+ * Filter the auto-login connection used by looking for a URL parameter.
+ *
+ * @param string $connection - name of the connection, initially pulled from Auth0 plugin settings.
*
* @return string mixed
*/
-function a0_docs_ex_auth0_get_auto_login_connection( $connection ) {
- // ... modify $connection
- return $connection;
+function auth0_docs_hook_auth0_get_auto_login_connection( ?string $connection ) {
+ return ! empty( $_GET['connection'] ) ? rawurlencode( $_GET['connection'] ) : $connection;
}
-add_filter( 'auth0_get_auto_login_connection', 'a0_docs_ex_auth0_get_auto_login_connection');
+add_filter( 'auth0_get_auto_login_connection', 'auth0_docs_hook_auth0_get_auto_login_connection' );
```
### wp_auth0_get_option
-This filter is used by option-getting functions and methods to modify the output value.
-
-**Example:**
+This filter is used by option-getting functions and methods to modify the output value.
```php
/**
- * @param mixed $value - value of the option, initially pulled from the database
- * @param string $key - key of the settings array
+ * Adjust an options value before use.
+ *
+ * @param mixed $value - value of the option, initially pulled from the database.
+ * @param string $key - key of the settings array.
*
* @return mixed
*/
-function a0_docs_ex_wp_auth0_get_option( $value, $key ) {
- // ... modify $value
+function auth0_docs_hook_wp_auth0_get_option( $value, string $key ) {
+ $value = 'bad_key' === $key ? 'That is a bad key and you know it' : $value;
return $value;
}
-add_filter( 'wp_auth0_get_option', 'a0_docs_ex_wp_auth0_get_option', 10, 2 );
+add_filter( 'wp_auth0_get_option', 'auth0_docs_hook_wp_auth0_get_option', 10, 2 );
```
### auth0_migration_ws_authenticated
-This filter is used in `WP_Auth0_Routes` to alter the WP_User object that is JSON-encoded and returned to Auth0
-during a user migration.
-
-**Example:**
+This filter is used in `WP_Auth0_Routes` to alter the WP_User object that is JSON-encoded and returned to Auth0 during a user migration.
```php
/**
- * @param WP_User $user - WordPress user object found during migration and authenticated
+ * Filter the WP user object before sending back to Auth0 during migration.
+ *
+ * @param WP_User $user - WordPress user object found during migration and authenticated.
*
* @return WP_User
*/
-function a0_docs_ex_auth0_migration_ws_authenticated( $user ) {
- // ... modify $user
+function auth0_docs_hook_auth0_migration_ws_authenticated( WP_User $user ) {
+ $user->data->display_name = 'Sir ' . $user->data->display_name . ', Esquire';
return $user;
}
-add_filter( 'auth0_migration_ws_authenticated', 'a0_docs_ex_auth0_migration_ws_authenticated' );
+add_filter( 'auth0_migration_ws_authenticated', 'auth0_docs_hook_auth0_migration_ws_authenticated' );
```
### wpa0_should_create_user
-This filter is used in `WP_Auth0_Users` when deciding whether a user should be created. The initial value passed in
-is `TRUE`. If `FALSE` is returned for any reason, registration will be rejected and the registering user will see an
-error message (see `WP_Auth0_UsersRepo::create()`).
-
-**Example:**
+This filter is used in `WP_Auth0_Users` when deciding whether a user should be created. The initial value passed in is `TRUE`. If `FALSE` is returned for any reason, registration will be rejected and the registering user will see an error message (see `WP_Auth0_UsersRepo::create()`).
```php
/**
- * @param bool $should_create - should the user be created, initialized as TRUE
- * @param stdClass $userinfo - Auth0 user information
+ * Should a new user be created?
+ *
+ * @param bool $should_create - should the user be created, initialized as TRUE
+ * @param stdClass $userinfo - Auth0 user information
*
* @return bool
*/
-function a0_docs_ex_wpa0_should_create_user( $should_create, $userinfo ) {
- // ... modify $should_create
+function auth0_docs_hook_wpa0_should_create_user( bool $should_create, stdClass $userinfo ) {
+ $should_create = ( false === strpos( 'josh', $userinfo->email ) );
return $should_create;
}
-add_filter( 'wpa0_should_create_user', 'a0_docs_ex_wpa0_should_create_user' );
+add_filter( 'wpa0_should_create_user', 'auth0_docs_hook_wpa0_should_create_user' );
```
### auth0_login_css
-This filter is used to modify the CSS on the login page, including the login widget itself. This filter runs before
-CSS is retrieved from the wp-admin settings page.
-
-**Example:**
+This filter is used to modify the CSS on the login page, including the login widget itself. This filter runs before CSS is retrieved from the wp-admin settings page.
```php
/**
- * @param string $css, initialized as empty
+ * Add CSS to the Auth0 login form.
+ *
+ * @param string $css - initialized as empty.
*
* @return string
*/
-function a0_docs_ex_auth0_login_css( $css ) {
- // ... modify $css by replacing or concatenating
+function auth0_docs_hook_auth0_login_css( ?string $css ) {
+ $css .= '
+ body {background: radial-gradient(#01B48F, #16214D)}
+ #login h1 {display: none}
+ .login form.auth0-lock-widget {box-shadow: none}
+ ';
return $css;
}
-add_filter( 'auth0_login_css', 'a0_docs_ex_auth0_login_css' );
+add_filter( 'auth0_login_css', 'auth0_docs_hook_auth0_login_css' );
+```
+
+### auth0_login_form_tpl
+
+Filters the template used for the Auth0 login form. This should return a path to a file containing HTML that replaces what is in `wp-content/plugins/auth0/templates/auth0-login-form.php`. The standard Lock initiation JS looks for an ID attribute of `auth0-login-form` to instantiate the login form so make sure that's present or replace the `wp-content/plugins/auth0/assets/js/lock-init.js` file with your own.
+
+```php
+/**
+ * Override the Lock login form template.
+ *
+ * @param string $tpl_path - original template path.
+ * @param array $lock_options - Lock options.
+ * @param boolean $show_legacy_login - Should the template include a link to the standard WP login?
+ *
+ * @return string
+ */
+function auth0_docs_hook_auth0_login_form_tpl( string $tpl_path, array $lock_options, bool $show_legacy_login ) {
+ return get_stylesheet_directory_uri() . '/templates/auth0-login-form.html';
+}
+add_filter( 'auth0_login_form_tpl', 'auth0_docs_hook_auth0_login_form_tpl', 10, 3 );
+```
+
+### auth0_settings_fields
+
+This filter is used to modify an existing form field or to add a new one. This should return a modified `$options` array with your changes or additions. New fields must have a field callback, as shown below.
+
+```php
+/**
+ * Modify existing or add new settings fields.
+ *
+ * @param array $options - array of options for a specific settings tab.
+ * @param string $id - settings tab id.
+ *
+ * @return array
+ *
+ * @see WP_Auth0_Admin_Generic::init_option_section()
+ */
+function auth0_docs_hook_auth0_settings_fields( array $options, string $id ) {
+ switch ( $id ) {
+ case 'basic':
+ $options[] = array(
+ 'name' => __( 'A Custom Basic Setting' ),
+ 'opt' => 'custom_basic_opt_name',
+ 'id' => 'wpa0_custom_basic_opt_name',
+ 'function' => 'auth0_docs_render_custom_basic_opt_name',
+ );
+ break;
+ case 'features':
+ break;
+ case 'appearance':
+ break;
+ case 'advanced':
+ break;
+ }
+ return $options;
+}
+add_filter( 'auth0_settings_fields', 'auth0_docs_hook_auth0_settings_fields', 10, 2 );
+
+/**
+ * Callback for add_settings_field
+ *
+ * @param array $args - 'label_for' = id attr, 'opt_name' = option name
+ *
+ * @see auth0_docs_hook_auth0_settings_fields()
+ */
+function auth0_docs_render_custom_basic_opt_name( array $args ) {
+ $options = WP_Auth0_Options::Instance();
+ printf(
+ '',
+ esc_attr( $options->get_options_name() ),
+ esc_attr( $args['opt_name'] ),
+ esc_attr( $args['label_for'] ),
+ esc_attr( $options->get( $args['opt_name'] ) )
+ );
+}
+```
+
+### auth0_auth_scope
+
+This filter allows developers to add or change the scope requested during login. This can be used to add [custom claims](/api-auth/tutorials/adoption/scope-custom-claims#custom-claims) or request a Refresh Token.
+
+```php
+/**
+ * Add or modify requested Access Token scopes during login.
+ *
+ * @param array $scopes - current array of scopes to add/delete/modify
+ *
+ * @return array
+ */
+function auth0_docs_hook_auth0_auth_scope( array $scopes ) {
+ // Add offline_access to include a Refresh Token.
+ // See auth0_docs_hook_auth0_user_login() for how this token can be used.
+ $scopes[] = 'offline_access';
+ return $scopes;
+}
+add_filter( 'auth0_auth_scope', 'auth0_docs_hook_auth0_auth_scope' );
```
+### auth0_nonce_cookie_name
+
+Use this filter to modify the cookie name used for nonce validation. See the `auth0_state_cookie_name` filter below for an example.
+
+### auth0_state_cookie_name
+
+Use this filter to modify the cookie name used for the [state](/protocols/oauth2/oauth-state) parameter value. This can add a prefix or suffix or replace the string entirely. Make sure to use valid characters in any modifications made:
+
+> A `` can be any US-ASCII characters except control characters (CTLs), spaces, or tabs. It also must not contain a separator character like the following: ( ) < > @ , ; : \ " / [ ] ? = { }.
+
+Read more about the `Set-Cookie` HTTP response header at the [MDN's Set-Cookie documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie).
+
+```php
+/**
+ * Prefix state and nonce cookie names.
+ *
+ * @param string $cookie_name - Cookie name to modify.
+ *
+ * @return string
+ */
+function auth0_docs_hook_prefix_cookie_name( string $cookie_name ) {
+ return 'prefix_' . $cookie_name;
+}
+add_filter( 'auth0_state_cookie_name', 'auth0_docs_hook_prefix_cookie_name' );
+add_filter( 'auth0_nonce_cookie_name', 'auth0_docs_hook_prefix_cookie_name' );
+```
+
+### auth0_settings_constant_prefix
+
+Use this filter to change the prefix for the constant used to override plugin settings. Please note that this filter **must** run before the Auth0 plugin is loaded so it needs to be located in an [MU plugin](https://codex.wordpress.org/Must_Use_Plugins).
+
+```php
+/**
+ * Prefix used for constant-based options.
+ *
+ * @param string $prefix - Constant prefix to modify or replace.
+ *
+ * @return string
+ */
+function auth0_docs_hook_settings_constant_prefix( string $prefix ) {
+ // Replace the prefix with something else.
+ // return 'AUTH_ENV_';
+
+ // Prefix the prefix.
+ return 'PREFIX_' . $prefix;
+}
+add_filter( 'auth0_settings_constant_prefix', 'auth0_docs_hook_settings_constant_prefix' );
+```
+
+### auth0_authorize_url_params
+
+This filter allows developers to adjust the `/authorize` endpoint parameters as needed. The function must return a dictionary-type array of URL parameters. See the [Login section of the Authentication API docs](/api/authentication#login) for more information on how these parameters are used.
+
+```php
+/**
+ * Adjust the authorize URL parameters used for auto-login and universal login page.
+ *
+ * @param array $params - Existing URL parameters.
+ * @param string $connection - Connection for auto-login, optional.
+ * @param string $redirect_to - URL to redirect to after logging in.
+ *
+ * @return array
+ */
+function auth0_docs_hook_authorize_url_params( array $params, ?string $connection, string $redirect_to ) {
+ if ( 'twitter' === $connection ) {
+ $params[ 'param1' ] = 'value1';
+ }
+
+ if ( FALSE !== strpos( 'twitter', $redirect_to ) ) {
+ $params[ 'param2' ] = 'value2';
+ }
+
+ return $params;
+}
+add_filter( 'auth0_authorize_url_params', 'auth0_docs_hook_authorize_url_params', 10, 3 );
+```
+
+### auth0_authorize_url
+
+This filter allows developers to adjust the complete `/authorize` URL before use. The function must return a valid URL as a string. See the [Login section of the Authentication API docs](/api/authentication#login) for more information on how this URL is used.
+
+```php
+/**
+ * Adjust the authorize URL before redirecting.
+ *
+ * @param string $auth_url - Built authorize URL.
+ * @param array $auth_params - Existing URL parameters.
+ *
+ * @return mixed
+ */
+function auth0_docs_hook_authorize_url( string $auth_url, array $auth_params ) {
+
+ if ( 'twitter' === $auth_params['connection'] ) {
+ $auth_url .= '¶m1=value1';
+ }
+
+ if ( ! empty( $auth_params['display'] ) ) {
+ $auth_url .= '¶m2=value2';
+ }
+
+ $auth_url .= '¶m3=value3';
+ return $auth_url;
+}
+add_filter( 'auth0_authorize_url', 'auth0_docs_hook_authorize_url', 10, 2 );
+```
+
+### auth0_die_on_login_output
+
+This filter lets you modify or replace the HTML content passed to `wp_die()` when there is an error during login. This filter does not affect the verify email content (see [auth0_verify_email_page](#auth0_verify_email_page)).
+
+```php
+/**
+ * Filter the output of the wp_die() screen when the login callback fails.
+ *
+ * @see \WP_Auth0_LoginManager::die_on_login()
+ *
+ * @param string $html - Original HTML; modify and return or return something different.
+ * @param string $msg - Error message.
+ * @param string|integer $code - Error code.
+ * @param boolean $login_link - True to link to login, false to link to logout.
+ *
+ * @return string
+ */
+function auth0_docs_hook_die_on_login_output( string $html, string $msg, $code, string $login_link ) {
+ return sprintf(
+ 'Original: %s
+ Message: %s Code: %s Link: %s ',
+ esc_html( $html ),
+ sanitize_text_field( $msg ),
+ sanitize_text_field( $code ),
+ $login_link ? 'TRUE' : 'FALSE'
+ );
+}
+add_filter( 'auth0_die_on_login_output', 'auth0_docs_hook_die_on_login_output', 10, 4 );
+```
+
+### auth0_coo_auth0js_url
+
+This filter lets you override the default CDN URL for Auth0.js when loading the COO fallback page.
+
+### auth0_slo_return_to
+
+This filter lets you override the default `returnTo` URL when logging out of Auth0.
+
+```php
+/**
+ * URL to return to after logging out of Auth0.
+ *
+ * @param string $default_return_url - Return URL, default is home_url().
+ *
+ * @return string
+ */
+function auth0_wp_test_hook_auth0_slo_return_to( string $default_return_url ) {
+ $default_return_url = add_query_arg( 'cache-break', uniqid(), $default_return_url );
+ return $default_return_url;
+}
+add_filter( 'auth0_slo_return_to', 'auth0_docs_hook_auth0_slo_return_to', 10 );
+```
+
+### auth0_logout_url
+
+This filter lets you override the Auth0 logout URL. See the [Auth0 Logout page](/logout) for more information on how this is used.
+
+```php
+/**
+ * URL used to logout of Auth0.
+ *
+ * @param string $default_logout_url - Logout URL.
+ *
+ * @return string
+ */
+function auth0_docs_hook_auth0_logout_url( string $default_logout_url ) {
+ $default_logout_url = add_query_arg( 'federated', 1, $default_logout_url );
+ return $default_logout_url;
+}
+add_filter( 'auth0_logout_url', 'auth0_docs_hook_auth0_logout_url' );
+```
+
+### auth0_use_management_api_for_userinfo
+
+This filter determines whether or not user profile data retrieved from the Management API should when you're *not* using the Implicit Login Flow. Return a boolean `true` (default) to use the API, `false` to use the ID token.
+
+```php
+// Always use the ID token for user profile data.
+add_filter( 'auth0_use_management_api_for_userinfo', '__return_false', 100 );
+```
+
+### auth0_lock_options
+
+This filter can be used to modify the options for the embedded Lock login form used in shortcodes, widgets, and on the wp-login.php page when **Features > Universal Login Page** is turned off.
+
+```php
+/**
+ * Filter the options passed to Lock.
+ *
+ * @param array $options - Existing options built from plugin and additional settings.
+ *
+ * @return array
+ */
+function auth0_docs_hook_lock_options( array $options ) {
+ if ( ! empty( $_GET[ 'lock_language' ] ) ) {
+ $options['language'] = sanitize_title( $_GET[ 'lock_language' ] );
+ }
+ return $options;
+}
+add_filter( 'auth0_lock_options', 'auth0_docs_hook_lock_options', 10 );
+```
+
+### auth0_jwt_leeway
+
+This filter lets you adjust the leeway time used to validate ID tokens and should return a number of seconds as an integer.
+
+```php
+/**
+ * Filter the JWT leeway.
+ *
+ * @param integer $leeway - Existing JWT leeway time in seconds; default is 60.
+ *
+ * @return integer
+ */
+function auth0_docs_hook_jwt_leeway( ?int $leeway ) {
+ return 120;
+}
+add_filter( 'auth0_jwt_leeway', 'auth0_docs_hook_jwt_leeway' );
+```
+
+### auth0_jwt_max_age
+
+This filter lets you adjust the `max_age` URL parameter sent on the authorize URL.
+
+```php
+/**
+ * Filter the max_age login parameter.
+ *
+ * @param integer $max_age - Existing max_age time, defaults to empty.
+ *
+ * @return integer
+ */
+function auth0_docs_hook_jwt_max_age( ?int $max_age ) {
+ return 1200;
+}
+add_filter( 'auth0_jwt_max_age', 'auth0_docs_hook_jwt_max_age' );
+```
+
+### auth0_authorize_state
+
+This filter lets you filter the state data before being encoded and used for login. This data will be verified after a successful login and provided as-is for use.
+
+```php
+/**
+ * Add, modify, or remove state values on login redirect.
+ *
+ * @param array $state Current state array.
+ * @param array $auth_params Authorization URL parameters.
+ *
+ * @return array
+ */
+function auth0_docs_hook_authorize_state( array $state, array $auth_params ) {
+ $redirect_to = parse_url( $state['redirect_to'] ?? '' );
+ if ( '/checkout' === ( $redirect_to['path'] ?? '' ) ) {
+ $state['cart_id'] = namspace_get_cart_id();
+ }
+ return $state;
+}
+add_filter( 'auth0_authorize_state', 'auth0_docs_hook_authorize_state', 10, 2 );
+```
+
+## Additional Extensions
+
+Additional examples can be found [here](https://github.com/joshcanhelp/auth0-wp-test/blob/master/inc/hooks-other.php).
+
## Keep Reading
More information on the Login by Auth0 WordPress plugin:
@@ -228,6 +625,5 @@ More information on the Login by Auth0 WordPress plugin:
* [How does it work?](/cms/wordpress/how-does-it-work)
* [Install the plugin](/cms/wordpress/installation)
* [Configure the plugin](/cms/wordpress/configuration)
-* [JWT API authentication](/cms/wordpress/jwt-authentication)
* [Troubleshooting](/cms/wordpress/troubleshoot)
-:::
\ No newline at end of file
+:::
diff --git a/articles/cms/wordpress/how-does-it-work.md b/articles/cms/wordpress/how-does-it-work.md
index 7d4e262804..9b47083e4b 100644
--- a/articles/cms/wordpress/how-does-it-work.md
+++ b/articles/cms/wordpress/how-does-it-work.md
@@ -1,60 +1,60 @@
---
description: This page explains the scenarios of how Auth0 integrates with WordPress.
+topics:
+ - wordpress
+ - cms
+contentType: concept
+useCase:
+ - add-login
+ - build-an-app
+ - customize-connections
+ - secure-an-api
+ - manage-users
---
-
# How Auth0 Integrates with WordPress
-There are several business flows that can occur when integrating Auth0 with your WordPress site.
-
-
-
-## Scenario 1: A user that doesn't exist in WordPress, but exists in Auth0, attempts to log in.
-
-1. The user access your WordPress site's login page.
-2. The user provides their credentials.
-3. Auth0 attempts to authenticate the user.
-4. The Auth0-WordPress plugin receives the user's Auth0 profile.
-5. The Auth0-WordPress plugin checks to see if there is a user in the WordPress database with credentials that match their Auth0 `user_id`.
-
- * If there **is** a user whose credentials match an Auth0 `user_id`, the Auth0-WordPress plugin checks to see if there is a user with the same `email`.
- * If there **is not** a user whose credentials match an Auth0 `user_id`, the Auth0-WordPress plugin creates a new user profile and logs the user in.
-
-
-## Scenario 2: A user that exists in WordPress **and** in Auth0 attempts to log in.
-
-In this scenario, the user has existed in your WordPress database and Auth0 *prior* to you installing the Auth0-WordPress plugin.
-
-1. The user access your WordPress site's login page.
-2. The user provides their credentials.
-3. Auth0 attempts to authenticate the user.
-4. The Auth0-WordPress plugin receives the user's Auth0 profile.
-5. The Auth0-WordPress plugin checks to see if there is a user in the WordPress database with credentials that match their Auth0 `user_id`.
-6. Because the Auth0-WordPress plugin can't find a user whose WordPress database credentials match any of the Auth0 `user_id` fields, it will check if there is a user with the same `email`.
-7. The Auth0-WordPress plugin identifies a user with the provided `email`.
-8. The Auth0-WordPress plugin checks to see if the Auth0 user has verified their email.
-
- * If the user has **verified** their email, the Auth0-WordPress plugin will update the WordPress user's `user_id` and log the user in.
- * If the user has **not** verified their email, the Auth0-WordPress plugin will end the authentication process, indicating that the user needs to verify their email prior to proceeding.
-
-## Scenario 3: A newly-created WordPress user that exists in Auth0 attempts to log in.
-
-1. The user access your WordPress site's login page.
-2. The user provides their credentials.
-3. Auth0 attempts to authenticate the user.
-4. The Auth0-WordPress plugin receives the user's Auth0 profile.
-5. The Auth0-WordPress plugin checks to see if there is a user in the WordPress database with credentials that match their Auth0 `user_id`.
-6. The Auth0-WordPress plugin finds the user in the WordPress database using their Auth0 user_id, so it logs the user in.
-
-## Scenario: Data Migration
-
-If you enable [data migration](/connections/database/migrating), the Auth0-WordPress plugin will expose two secure endpoints that allow Auth0 authenticate the users. These endpoints are secured with a secret token and only available to IP addresses associated with Auth0. You can change this in the Auth0 Dashboard's Application [Advanced Settings](${manage_url}/#/applications) page.
-
-The login flow is as follows:
-
-1. The user access your WordPress site's login page and provides their credentials.
-2. Auth0 can't find a user associated with the provided credentials, so it proceeds to call the migration endpoint.
-3. The Auth0-WordPress plugin find a user in your WordPress database with the provided username/email, so it verifies the password.
-4. Auth0 creates the user in your Auth0 account, authenticates the user, and logs them in.
+The Login by Auth0 plugin handles login and account creation flows automatically by creating or matching user accounts with incoming Auth0 profile data. The login process and the signup process are similar and an account will be created or matched based on the data in your WordPress database rather than the initial action taken. In other words, logging in via Auth0 can create a WordPress account and signing up via Auth0 can match an existing WordPress account.
+
+ ::: note
+ If you are using the User Migration setting in the plugin, the login flow will be slightly different than what is explained below. Please see our documentation on [User Migration in WordPress](/cms/wordpress/user-migration).
+ :::
+
+The process runs as follows:
+
+1. The user accesses the WordPress site's login page. This could be the main login page at `[SITE URL]/wp-login.php` or a page containing a widget or shortcode.
+2. The user provides their username and password, clicks on a social icon to use another identity provider, or completes the Passwordless process in the Auth0 login form, Lock.
+3. Auth0 attempts to authenticate the user with the method selected.
+ - If login or signup with a username + password or with Passwordless fails, an error message will appear on Lock.
+ - If it is successful, the process continues below.
+4. The user is redirected to the `/authorize` endpoint with a login ticket and a `state` value generated by the plugin. Once this is complete, the Auth0 user record has been created and the rest of the process happens on the WordPress site.
+5. The actual login process differs whether you are using the Authorization Code Flow or the Implicit Flow ("Implicit Login Flow" on the Advanced tab of the plugin settings is turned off [default] for the former, on for the latter):
+ - For [Authorization Code Flow](/flows/guides/auth-code/add-login-auth-code) logins:
+ 1. The user is redirected back to a callback URL, `SITE URL/index.php?auth0=1` with an authorization code and the same `state` value in URL parameters.
+ 2. The `state` value is validated. If validation does not pass, an "Invalid state" error is shown and the login process stops ([see the Troubleshooting page](/cms/wordpress/troubleshoot) for more information on state validation).
+ 3. The ID token is validated to make sure nothing was modified during transit. If the ID token is invalid, an error message is shown and the login process stops ([see the Troubleshooting page](/cms/wordpress/troubleshoot) for more information on ID token validation)
+ 4. The user profile data is retrieved via the Management API using the [Machine-to-Machine Flow](/flows/concepts/client-credentials).
+ - For [Implicit Flow](/flows/guides/implicit/add-login-implicit) logins:
+ 1. The user is redirected back to a callback URL, `SITE URL/wp-login.php?auth0=implicit` with an ID token and the same `state` value in an anchor link.
+ 2. This anchor link is [parsed in JS](https://github.com/auth0/wp-auth0/blob/master/assets/js/implicit-login.js) and then POSTed back to a callback URL `SITE URL/index.php?auth0=implicit` with those 2 same values in URL parameters.
+ 3. The ID token is validated to make sure nothing was modified during transit. If the ID token is invalid, an error message is shown and the login process stops ([see the Troubleshooting page](/cms/wordpress/troubleshoot) for more information on ID token validation)
+ 4. The information in the valid ID token is used as the user profile data.
+6. At this point, the Auth0 authentication process is complete and the plugin attempts to match the profile data with a user in WordPress.
+7. The plugin checks whether the site requires an email address (plugin settings **Advanced** tab) and if the incoming profile has an `email_verified` flag set.
+ - If the site requires an email address and the incoming user does not provide an email address (some social identity providers, like Twitter, do not include an email address), the login process stops with an error message stating "This account does not have an email associated."
+ - If the site requires an email address and the incoming user does not have the `email_verified` flag set to `true`, the login process stops with an error message stating "This site requires a verified email address" and a link to re-send the verification email. This will continue to show until the user successfully verifies their email address.
+ - If the site does not require an email address or the incoming user has the `email_verified` flag set to `true`, then the login process continues.
+8. The plugin checks to see if there is a user in the WordPress database with a `usermeta` value that matches the incoming Auth0 user ID (meaning that the user has signed up or logged in with Auth0 before):
+ - If a user is found that has the incoming user ID then the login process continues.
+ - If a user was not found with the incoming Auth0 user ID, the plugin will look for an email address matching the incoming user:
+ - If a match is found, that user is selected and the login process continues.
+ - If a match is not found, the plugin check if registration is turned on for the WordPress site:
+ - If registration is turned off, the login process stops with an error message stating `Could not create user. The registration process is not available.`
+ - If registration is turned on, a new user is created and the login process continues.
+9. The found or created user is updated with the incoming Auth0 profile data, including their Auth0 user ID.
+10. The user is logged into their WordPress account with `wp_set_auth_cookie` and the core `do_login` action fires.
+11. Finally, the user is redirected to a page on the site (this could be the default one set in the plugin settings **Advanced** tab or the original login URL if a shortcode or widget was used or a different one provided during the login process).
+
+The user is now logged into Auth0 and their WordPress account with the two associated by their Auth0 user ID.
## Keep Reading
@@ -63,7 +63,6 @@ More information on the Login by Auth0 WordPress plugin:
::: next-steps
* [Install the plugin](/cms/wordpress/installation)
* [Configure the plugin](/cms/wordpress/configuration)
-* [JWT API authentication](/cms/wordpress/jwt-authentication)
* [Troubleshooting](/cms/wordpress/troubleshoot)
* [Extend the plugin](/cms/wordpress/extending)
-:::
\ No newline at end of file
+:::
diff --git a/articles/cms/wordpress/index.md b/articles/cms/wordpress/index.md
index 1e86665b20..bbdf88e486 100644
--- a/articles/cms/wordpress/index.md
+++ b/articles/cms/wordpress/index.md
@@ -1,23 +1,36 @@
---
description: This page explains the basics of the Login by Auth0 WordPress plugin.
url: /cms/wordpress
+topics:
+ - wordpress
+ - cms
+contentType:
+ - index
+ - concept
+useCase:
+ - add-login
+ - build-an-app
+ - customize-connections
+ - secure-an-api
+ - manage-users
---
# Login by Auth0 WordPress Plugin

-Auth0 provides a WordPress Plugin to integrate your sites with your Auth0 account. This plugin enables Single Sign On for Enterprises, social login, user/password and passwordless login through all your instances.
+Auth0 provides a WordPress Plugin to integrate your sites with your Auth0 account. This plugin enables Single Sign-on (SSO) for Enterprises, social login, user/password, and passwordless login through all your instances.
Login features are implemented through a new form (powered by Auth0) that enables:
-- Single Sign On with Enterprise Directories (LDAP, AD, Google Apps, Office365 and SAML Provider)
-- Single Sign On with over 30 [Social Providers](/identityproviders)
-- Single Sign On between WordPress installs and other applications
+- SSO with Enterprise Directories (LDAP, AD, G Suite, Office365, and SAML Provider)
+- SSO with over 30 [Social Providers](/identityproviders)
+- SSO between WordPress installs and other applications
- User Management Dashboard
-- Optional Multifactor Authentication
+- Optional Multi-factor Authentication
- Optional Passwordless Authentication
- Reporting and Analytics
+
## Keep Reading
diff --git a/articles/cms/wordpress/installation.md b/articles/cms/wordpress/installation.md
index 894f6af7ee..09e513a4d0 100644
--- a/articles/cms/wordpress/installation.md
+++ b/articles/cms/wordpress/installation.md
@@ -1,65 +1,111 @@
---
description: Explains how to install the Auth0 WordPress plugin.
+topics:
+ - wordpress
+ - cms
+contentType: how-to
+useCase:
+ - add-login
+ - build-an-app
+ - customize-connections
+ - secure-an-api
+ - manage-users
---
-# Installation of the Login by Auth0 WordPress Plugin
+# Installing Login by Auth0
::: note
In order to install or customize plugins, you must use a self-hosted WordPress.org site. Using a WordPress.com site does not allow installing plugins. [More information on the differences here](https://en.support.wordpress.com/com-vs-org/).
:::
-Plugins can be added to your WordPress site automatically or manually. Both processes are covered [here in the WordPress Codex](https://codex.wordpress.org/Managing_Plugins#Installing_Plugins).
+This plugin can be added to your WordPress site using the **Plugins** screen in the wp-admin:
+
+1. Log into an existing WordPress site as an administrator.
+2. Go to **Plugins > Add New** in the admin menu on the left.
+3. Search for "Login by Auth0"
+4. For the Login by Auth0 plugin, click **Install Now**, then **Activate**.
+
+This process and other methods are covered [in the WordPress documentation](https://wordpress.org/support/article/managing-plugins/#installing-plugins).
As soon as the plugin is activated, you are redirected to the start of the Setup Wizard.
-
+If you don't already have an Auth0 account, click the **[Sign Up For Free](https://auth0.com/signup).** button and create one before proceeding.
-If you don't already have an Auth0 account, click the **[Sign Up For Free](https://auth0.com/signup).** button and create one before proceeding.
+::: note
+Auth0 will not replace your login forms until a **Domain**, **Client ID**, and **Client Secret** have been added to the Basic tab of the settings page.
+:::
-## Manual setup
+## Multisite setup
-The plugin can be configured using the built-in setup wizard (covered below) or manually by creating an Application and
-assigning connections. The completely manual setup process can be used if you're having trouble with the
-wizard, have been through the setup process before, or want to share a database connection between Applications.
+The Login by Auth0 plugin is compatible with WordPress multisite networks. The plugin can be network activated to automatically protect network sites (once configuration is complete) or activated only on a sub-set of the network.
-1. In your Auth0 [Dashboard](${manage_url}), click **Applications** then **Create Application**
-1. Give your Application a descriptive name, select **Regular Web Applications**, then **Create**
-1. Follow the [Application setup instructions](/cms/wordpress/configuration) closely through the "Update Auth0 settings in
-WordPress" section to configure the application for your WordPress installation
+There are a few ways that a network of sites can be setup in Auth0:
-Once the steps above are complete, your site will be configured and ready to use!
+1. **All sites can share both an Application and a database connection**
+ 1. Run the Setup Wizard steps to completion for the main site.
+ 2. Setup all other sites manually using the **Domain**, **Client ID**, and **Client Secret** from the main site in the Basic tab of the Auth0 settings page.
+ 3. Update the Application's **Allowed Callback URLs**, **Allowed Web Origins**, and **Allowed Logout URLs** to include each site (wildcards can be used if your network uses subdomains).
+1. **Each site can have its own Application and share a database connection**
+ 1. Run the Setup Wizard steps to completion for the main site.
+ 2. Next, create an Application for each of the sites [manually](/cms/wordpress/configuration) and add each one to the previously-created database connection.
+ 3. Add the **Domain**, **Client ID**, and **Client Secret** values to the Basic tab of the Auth0 settings page for each site.
+1. **Each site can have its own Application and its own database connection.** In this case, Run the Setup Wizard steps to completion for each site.
-## Wizard - Social Login
+Each of the options above has trade-offs. Option 1 has the least number of different entities to manage in Auth0 but, if your network has hundreds of sites and you're not using subdomains, you might run into limitations with the number of callback URLs. Option 2 will require managing many different Applications but will allow you to configure each site's Application differently.
-Click **Social** to start the basic Auth0 setup.
+As always, if you have any questions about this setup process, create a post on our [Community](https://community.auth0.com/tags/wordpress) tagged "wordpress."
-### Automatic
+## Setup Wizard
-Public servers that allow incoming connections from Auth0 will begin the Automatic setup process. Authorize the WordPress site for your tenant and everything will be setup automatically, including user migration.
+The Setup Wizard will attempt to create all the necessary components needed to use Auth0 on your WordPress site. If you have an existing Application or Database Connection you want to use, please see the [Manual Setup](#manual-setup) steps below.
-
+### Option 1: Standard Setup
+
+This will create and configure an Application and a Database Connection for this site.
+
+First, [follow the instructions](/api/management/v2/get-access-tokens-for-test#get-access-tokens-manually) for generating a Management API token. Once the token is generated, make a note of the domain name used in the **Identifier** field under the **Settings** tab. For example, if your Identifier is `https://tenant-name.auth0.com/api/v2/`, then the tenant domain is `tenant-name.auth0.com`. [More about tenant Domains can be found here](/getting-started/the-basics#domains).
+
+Back in the WordPress admin's Setup Wizard, click **Standard**. In the modal that appears, click **Start Standard Setup**.
+
+
+
+Enter the tenant domain and API token from above. This token is only used for the setup process and will not be saved in the database.
+
+If the first part of the setup successfully completes, you'll see the "Configure your social connections" screen. Click **Next** to continue the setup process by migrating your administrator account.
+
+
-### Manual
+This step connects your WordPress user with an Auth0 user that authorizes you to log in. You can choose the same password as your admin account or different but make sure it conforms to the [password policy described here](/connections/database/password-strength#password-policies) for the database Connection being used.
-This process is used for servers without incoming connections from Auth0, such as a local development machine or a server with access blocked by a firewall or other protection.
+The Setup Wizard must run to completion for your site to be setup correctly. If the Wizard fails for any reason before the "setup successful" screen, check the plugin error log at **wp-admin > Auth0 > Error Log** and the steps below to determine the issue.
-
+To start the process over completely, delete any Applications or Database Connections that were created in the Auth0 Dashboard. In WordPress, to go **Auth0 > Settings > Basic**, delete the Domain, Client ID, and Client Secret fields, and click **Save**. Now, click **Setup Wizard** in the admin menu to start the process over again.
-In the modal that appears, enter the domain name for your tenant and a valid, manually-generated Access Token. [Follow the instructions here](/api/management/v2/tokens#get-a-token-manually) - "Get a token manually" section - to create the token and find your domain.
+If you're still not able to install, [please post a thread in our Community](https://community.auth0.com/tags/wordpress) with the error messages you're seeing in the Error Log and we'll be happy to help!
-If the first part of the setup successfully completes, you'll see the "Configure your social connections" screen. If not, to go **Auth0 > Settings > Basic**, delete your Client ID and domain, then click **Setup Wizard** in the admin menu to start again. Check the Auth0 Error Log in wp-admin for more information about what went wrong and [post in our Community](https://community.auth0.com/topics/wordpress) if you need support.
+### Option 2: User Migration Setup
-Click **Next** to continue the setup process by migrating your administrator account.
+This will create and configure an Application and a database connection plus data migration from your WordPress database. This requires an inbound connection from Auth0 servers and cannot be changed later without losing data. [More information on user migration is here](/cms/wordpress/user-migration).
-
+::: warning
+If you have more than one custom database connection in Auth0, you'll need to make sure that the user IDs are namespaced to avoid conflicts. This is done automatically for sites installing version 3.11.0 or later. If your connections are/were being created with an earlier version, please see the [troubleshooting steps here](/cms/wordpress/user-migration#cannot-change-email-or-incorrect-user-data).
+:::
+
+
+
+Once the setup process is complete, log out of your WordPress site and attempt to log back in using your existing WordPress credentials in the Auth0 login form. This should create an Auth0 user linked to your WordPress account.
+
+### Option 3: Manual Setup
-This step connects your WordPress user with an Auth0 user that authorizes you to log in. You can choose the same password as your admin account or different but make sure it conforms to the ["Fair" password policy described here](/connections/database/password-strength#password-policies) (the default for this plugin).
+This will skip the automatic setup and allow you to create and configure your own Application and database connection ([see below](#manual-setup)). This should be used if you want this site to use an existing Application or database connection.
+
+### Option 4: Import Setup
+
+The site can also be set up by importing settings from another site. This is useful if you're migrating between environments or have a similar WordPress site that's already setup.
## Setup complete
When you see the "Done" screen, Auth0 is setup and ready to accept logins and, if configured, signups!
-
-
This is a good time to confirm that the basics are working for your site before changing any of the default settings:
1. Log out of WordPress and confirm that the Auth0 form now appears at `/wp-login.php`.
@@ -69,14 +115,25 @@ This is a good time to confirm that the basics are working for your site before
Now you're ready to [Configure](/cms/wordpress/configuration)!
-## Keep Reading
+## Manual setup
+
+The plugin can be configured using the built-in setup wizard (covered below) or manually by creating an Application and
+assigning connections. The completely manual setup process can be used if you're having trouble with the
+wizard, have been through the setup process before, or want to share a database connection between Applications.
+
+1. In your Auth0 [Dashboard](${manage_url}), click **Applications** then **Create Application**
+1. Give your Application a descriptive name, select **Regular Web Applications**, then **Create**
+1. Follow the [Application setup instructions](/cms/wordpress/configuration) closely through the "Update Auth0 settings in WordPress" section to configure the application for your WordPress installation
+
+Once the steps above are complete, your site will be configured and ready to use!
+
+## Keep reading
More information on the Login by Auth0 WordPress plugin:
::: next-steps
* [How does it work?](/cms/wordpress/how-does-it-work)
* [Configure the plugin](/cms/wordpress/configuration)
-* [JWT API authentication](/cms/wordpress/jwt-authentication)
* [Troubleshooting](/cms/wordpress/troubleshoot)
* [Extend the plugin](/cms/wordpress/extending)
:::
diff --git a/articles/cms/wordpress/invalid-state.md b/articles/cms/wordpress/invalid-state.md
new file mode 100644
index 0000000000..1a0f862a22
--- /dev/null
+++ b/articles/cms/wordpress/invalid-state.md
@@ -0,0 +1,128 @@
+---
+description: Troubleshooting invalid state errors in the Login by Auth0 WordPress plugin.
+topics:
+ - wordpress
+ - cms
+ - state
+contentType: reference
+useCase:
+ - add-login
+ - build-an-app
+ - customize-connections
+ - secure-an-api
+ - manage-users
+---
+
+# Troubleshoot WordPress Plugin Invalid State Errors
+
+We added state validation to the WordPress plugin in [version 3.6.0](https://github.com/auth0/wp-auth0/releases/tag/3.6.0). This security measure helps mitigate CSRF attacks by ensuring that the response belongs to a request initiated by the same user For more information, see [State Parameter](/protocols/oauth2/oauth-state).
+
+## How state validation works
+
+The plugin performs state validation by:
+
+1. Setting an `auth0_state` cookie in the browser via Javascript when the Lock login form is shown (on `wp-login.php` or any other page when using a shortcode or widget).
+2. Passing that value to the Lock embedded login form so it can be sent with the authentication request.
+3. Receiving that value back from Auth0 unchanged in a `state` URL parameter if the Auth0 login was successful.
+4. Validating the that value received matches the value sent and stored in the `auth0_state` cookie. If it's valid, then the login process continues. If not, the process stops and an "Invalid state" error message is shown.
+5. Deleting the cookie, regardless of validity.
+6. Using values in the base64 decoded object to redirect or perform other login actions, if valid.
+
+This process should be completely opaque to both the logging-in user and the site admin. The Auth0 server does not validate or require a state value and returns it untouched to the callback URL. If the "Invalid state" message is seen, then one of the first 4 steps above is not happening.
+
+## Common causes of the invalid state error
+
+Below are some common causes of the invalid state error as well troubleshooting steps you can take.
+
+### Cached callback URLs
+
+The most common cause of the invalid state error is when the callback URL is cached on the server.
+
+Exclude caching on your server for all the URLs listed in the **Allowed Callback URLs** field for your [Application Settings](${manage_url}/#/applications/${account.clientId}/settings) in the Auth0 Dashboard and test again. In addition, exclude caching the site URL (`/index.php` on a regular install) if it has an Auth0 URL parameter.
+
+Check to see if your server’s time is not set properly. The `BeforeValidException` error can occur when the token is perceived to have been generated before the current time, which can happen if the server times are off. You can check server time by using `echo current_time( 'c' )`. A temporary workaround may also be to modify the plugin to add a time offset if you cannot modify the server time, but it should be fixed for production.
+
+If that does not solve the issue, continue with the troubleshooting steps below.
+
+### Cached cookies and URL parameters
+
+If you're on a managed host like WP-Engine, you may need to contact their support team for additional assistance. We've had reports of issues accessing required cookies on the callback URL, as well as problems with checking authentication on the final page that users see after logging in. Specifically, ask to have cache exclusions added for:
+
+- **Cookie:** `auth0_state`
+- **Cookie:** `auth0_nonce`
+- **Arg/URL parameter:** `auth0`
+- **Arg/URL parameter:** `code`
+- **Arg/URL parameter:** `state`
+- **Arg/URL parameter:** `id_token`
+
+### Page refresh after error message
+
+If you refresh the page after seeing a different error message (email verification, etc) the invalid state message will appear, as it’s trying to revalidate an already used value. This is expected.
+
+### Cookie names requirement
+
+Some hosts, like Pantheon, require specific cookie names to be used. You can alter the cookie name using the [`auth0_state_cookie_name`](/cms/wordpress/extending#auth0_state_cookie_name) filter (see the [issue here](https://github.com/auth0/wp-auth0/issues/494) and [fix here](https://github.com/auth0/wp-auth0/pull/495)) in your theme or a custom plugin.
+
+### Universal Login Page and link building
+
+If your site is using the Universal Login Page and you're building the link yourself in a theme or plugin, you need to:
+
+* Set a cookie called `auth0_state` with a randomly-generated value
+* Send that value in a `state` URL parameter.
+
+Alternatively, you can go to Settings > Features tab > Universal Login Page and redirect login requests to the `wp-login.php` page where that cookie and URL parameter will be set automatically. The code that runs this process is [here](https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_LoginManager.php#L90) if you want to continue to use a custom-built `/authorize` URL.
+
+### Visiting the callback URL directly
+
+If you visit your callback URL (typically `yourdomain.com/index.php?auth0=1`) directly or a second time after the authorization code has been exchanged, the invalid state error might display. This indicates that the state has already been verified and deleted.
+
+## Troubleshoot invalid state errors
+
+Note that some of the steps below will require the login process to be broken during the process (marked as such):
+
+1. While logged out of WordPress and Auth0, visit the login page being tested.
+2. Check if the `auth0_state` cookie is being set (in Chrome, View > Developer > JavaScript Console > Application tab > Storage on the left > Cookies > domain being tested, look for an `auth0_state` cookie with a non-empty value).
+
+ * If this value is not set, check for errors in the JS console and that your browser can accept cookies (login will not work without cookies). This is set in `/assets/js/lock-init.js` ([code on GitHub](https://github.com/auth0/wp-auth0/blob/master/assets/js/lock-init.js#L22))
+ * If the value is set, copy the value and view the source code of the page (in Chrome, **View** > **Developer** > **View Source**). Search for the value, and it should appear as the value associated with parameter `wpAuth0LockGlobal.settings.auth.params.state` ([sample JSON](https://gist.github.com/joshcanhelp/1b8bb990048325eb7214e2b3d7136b78)). Make a note of this value (you'll need it in a following step).
+
+3. If the value appears there and the Lock form is loading normally then steps 1 and 2 from the first list above are functioning properly.
+4. Before logging in, add [this snippet](https://gist.github.com/joshcanhelp/ba98f748747c7fd2ecdf54e73c6110f3) to the top of your `wp-config.php`. **WARNING**: This will break login for the WordPress site being tested so use it only on a non-production install.
+5. Log in normally.
+6. After you're redirected back to your site's callback URL, the process will stop. You should see an output like what's shown in the linked Gist in step #4 above. If you see something like `Array()` with no additional values, then one of two things could be happening:
+
+ * The WordPress callback URL is cached. Page caching can happen in many different ways so there are not explicit steps we can provide here. Check any caching plugins you may have installed, they usually have some kind of URL exclusion built-in. Also check with your host as caching may be automatic and require support involvement.
+ * The server is not reading the Auth0 cookie. See the [issue here](https://github.com/auth0/wp-auth0/issues/494) and [fix here](https://github.com/auth0/wp-auth0/pull/495) for a possible solution.
+
+7. If the values are present, check the response headers for the callback URL being loaded (in Chrome, View > Developer > JavaScript Console > Network tab, click the first "document" listed with a 500 status and look for "Response Headers"). Look for any evidence of caching here, like a `Cache-Control` with a non-zero `max-age`, an `x-cache` of something other than `MISS`, or any other clue that this page is being served from a cache.
+8. Also in the response headers, check that `set-cookie` includes a directive like `auth0_state=deleted` to confirm the validation process is happening.
+9. Make sure that the `state` parameter in the URL matches the one recorded from the cookie being set in step #3 above.
+10. If there is no evidence of caching, remove the debugging snippet from `wp-config.php` and refresh the callback URL. You should see the "Invalid state" message again. If any caching changes were made, attempt the login process all the way through (make sure to clear your cookies and browser cache for the site before testing).
+
+The following troubleshooting steps require plugin changes that will break the login process and need to be rolled back once complete. These steps should be performed on a test or staging server.
+
+11. Next, we need to check why the state is coming in but does not match the stored value.
+12. In `lib/WP_Auth0_LoginManager.php`, output the values of the stored and returned state and kill the process after. Just before [this line](https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_LoginManager.php#L148), add:
+
+```php
+echo '
$_REQUEST
'; var_dump($_REQUEST); echo '
$_COOKIE
'; var_dump($_COOKIE); die('
Done
');
+```
+
+13. Once again, make sure you're logged out and complete the login process.
+14. You should see values output when redirected back to the WordPress callback URL.
+15. Check if the `state` value in `$_REQUEST` exists and matches the `auth0_state` value in `$_COOKIE`.
+
+ * If it's different, it should match the original value recorded in step #3 above. This means that the `$_COOKIE` state value has changed somewhere in the process.
+
+If none of the steps above resolve the issue, please collect the results of the steps above and [contact support](https://support.auth0.com/) or post on [Community](https://community.auth0.com/tags/wordpress) with the tag `wordpress`. Also include:
+
+- PHP version
+- WordPress version
+- Auth0 plugin version
+- Browser and OS used to test
+- A [HAR file](/troubleshoot/guides/generate-har-files) recording the entire process from loading the page with the login form all the way through the "Invalid state" message.
+
+## Related posts:
+
+- ["Invalid state" error during Auth0 WordPress redirect](https://community.auth0.com/t/invalid-state-error-during-auth0-wordpress-redirect/12552/16)
+- [Invalid state when visiting the callback URL directly](https://wordpress.org/support/topic/unable-to-resolve-troubleshooting-with-a-client-grant-for-already-exists/)
diff --git a/articles/cms/wordpress/jwt-authentication.md b/articles/cms/wordpress/jwt-authentication.md
deleted file mode 100644
index bb68242cb6..0000000000
--- a/articles/cms/wordpress/jwt-authentication.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-description: Explains how to install the WordPress JWT Authentication and integration with the Auth0 plugin.
----
-
-# WordPress JWT Authentication
-
-::: warning
-The WordPress JWT Authentication plugin is deprecated and will no longer be updated by Auth0.
-:::
-
-Auth0 provides a plugin to enable [JWT](/jwt) authentication for your APIs. It is compatible with any API that uses the `determine_current_user` function to retrieve the logged in user (such as [WP REST API](https://wordpress.org/plugins/json-rest-api/)).
-
-## Installation
-
-You can install the plugin using either of the following methods:
-
-1. Install **WordPress JWT Authentication** from the WordPress Store;
-2. Download the zip file from [WordPress JWT Authentication](https://wordpress.org/plugins/wp-jwt-auth/) and upload the `wp-jwt-auth` folder to the `/wp-content/plugins/` directory your WordPress installation.
-
-After installation, activate the plugin through the **Plugins** menu in WordPress.
-
-## Configure the Plugins' Settings
-
-After you've activated your plugin, provide the following values for your Auth0 account:
-
-- **Aud:** Usually your *Client Id*. Verifies that the token was intended for you.
-- **Secret:** Your *Client Secret*. Verifies the token signature.
-- **Base64 Secret Encoded:** If enabled, encodes the secret in based64.
-- **User Repository:** Empty by default. If empty, the plugin checks for a user whose `User Property` matches the `JWT Attribute` defined in each field. You can create a custom *User Repository* by implementing a static method called `getUser` to receive the decoded JWT and return a `WP_User` instance.
-
-## Integration with the Auth0 WordPress plugin
-
-If you've also installed and enabled the latest version of the [Auth0 WordPress Plugin](/cms/wordpress/how-does-it-work), you can opt to configure the Auth0 WordPress plugin automatically, which sets your *client id*, *client secret* and the *Auth0 User Repository*.
-
-## Authenticating requests
-
-To authenticate a request using JWT, add an `Authorization` header to the request:
-
-```txt
-Authorization: Bearer YOUR-TOKEN
-```
-
-for example:
-
-```txt
-Authorization: Bearer eyJhbGciOiJIUzIsNiIsInR5cCI6IkpXVCJ9.
-eyJjb250ZW50IjoiVGhpcyBpcyB5b3VyIHVzZXIgSldUIHByb3ZpZGVkIG
-J5IHRoZSBBdXRoMCBzZXJ2rXIifQ.b47GoWoY_5n4jIyGghPTLFEQtSegn
-Vydcvl6gpWNeUE
-```
-
-## Resources
-
-- [Cookies vs Tokens. Getting auth right with Angular.JS](https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/)
-- [10 Things You Should Know about Tokens](https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/)
-
-## Keep Reading
-
-More information on the Login by Auth0 WordPress plugin:
-
-::: next-steps
-* [How does it work?](/cms/wordpress/how-does-it-work)
-* [Install the plugin](/cms/wordpress/installation)
-* [Configure the plugin](/cms/wordpress/configuration)
-* [Troubleshooting](/cms/wordpress/troubleshoot)
-* [Extend the plugin](/cms/wordpress/extending)
-:::
diff --git a/articles/cms/wordpress/troubleshoot.md b/articles/cms/wordpress/troubleshoot.md
index a5493834d5..b694b8ad52 100644
--- a/articles/cms/wordpress/troubleshoot.md
+++ b/articles/cms/wordpress/troubleshoot.md
@@ -1,66 +1,138 @@
---
-description: This page explains common troubleshooting issues with WordPress.
+description: This page explains common troubleshooting issues with the Login by Auth0 WordPress plugin.
+toc: true
+topics:
+ - wordpress
+ - cms
+contentType: reference
+useCase:
+ - add-login
+ - build-an-app
+ - customize-connections
+ - secure-an-api
+ - manage-users
---
+# Troubleshooting Login by Auth0
-# WordPress Troubleshooting
+Here are some common troubleshooting questions. If the items below do not solve your issue, then consider the following alternatives:
-## I'm seeing a message "This account does not have an email associated..." that stops me from logging in.
+* If you're setting up the plugin for the first time or having problems with users logging in, please review the [configuration](/cms/wordpress/configuration) page in this section.
+* If you found a bug in the plugin code [submit an issue](https://github.com/auth0/wp-auth0/issues) or [create a pull request](https://github.com/auth0/wp-auth0/pulls) on GitHub.
+* If you have questions about how to use Auth0 or the plugin, please [post on our community site](https://community.auth0.com/) or create a [support forum request here](https://wordpress.org/support/plugin/auth0).
+* You can also see additional documentation and answers on our [support site](https://support.auth0.com/). Customers on a paid Auth0 plan can [submit a trouble ticket](https://support.auth0.com/tickets) for a fast response.
-If you get this error, make sure you are requesting an email from each provider in the Auth0 Dashboard under Connections -> Social (expand each provider). Take into account that not all providers return email addresses for users (e.g. Twitter). If this happens, you can always add an Email address to any logged in user through the Auth0 Dashboard (or API). See Users -> Edit.
+## I'm seeing the error message "Invalid state" that prevents me from logging in
-## I'm getting a "Failed cross origin authentication" or "No verifier returned from client" error in my error logs or when logging in.
+State validation is a security feature added in [version 3.6.0](https://github.com/auth0/wp-auth0/releases/tag/3.6.0). A cached callback URL usually causes this error message (see your Application settings for the callback URLs that should not be cached). If this is not the issue or you need more information, please see [Troubleshoot WordPress Plugin Invalid State Errors](/cms/wordpress/invalid-state).
-Check your "Allowed Callback URLs" and "Allowed Origins (CORS)" fields in the Application settings for your WordPress site to make sure those are correct. If you're using a Chromium-based browser, review our [docs page on cross-origin authentication](/cross-origin-authentication#limitations-of-cross-origin-authentication) to make sure you don't have third-party cookies turned off.
+## I'm having an issue logging in or changing email/password using a custom database
-## The Auth0 settings page in WordPress displays the warning: "The current user is not authorized to manage the Auth0 account...".
+[Please see our specific troubleshooting page](/cms/wordpress/user-migration#troubleshooting).
-If you updated your plugin to version 2 or configured the plugin without following the Quick Start Guide, you may need to provide an API token that the plugin will use to update your account settings. You can [generate a new token](/api/v2) and enter it into the **App Token** field of the the **Basic** settings page of the plugin. (The required scopes for the token are listed there.) You can also ignore this warning. Some operations will not be available from the plugin (like enabling rules or SSO). You will need to make these configuration changes manually in the [Auth0 dashboard](${manage_url}/#/applications).
+## I'm seeing the error message "Invalid ID token" or "Expired ID token" that prevents me from logging in
-## I have two accounts for the same user in WordPress.
+This is typically caused by a server set to an incorrect time. If the error message includes "used too early," then your server time is set in the future. If it says that the token is expired, then the server time is set too far in the past. A difference in time between two servers is common. Output `echo date(DateTime::ISO8601)` in PHP on your server and compare that, including seconds, to the current UTC time. If your server's time is more than 60 seconds (the default leeway) off from UTC time, then you’ll need to set a longer leeway to account for your server’s clock skew. You can paste the below code in your theme's `functions.php` or anywhere else that would run it after the plugin loads and before the login hook runs:
-Under some situations, you may end up with a user with two accounts. WordPress allows you to merge users by deleting one of the accounts and attributing that account's content to another user. Go to wp-admin > Users, select the account you want to delete, and in the confirmation dialog select another user to transfer the content.
+```
+add_filter( 'auth0_jwt_leeway', function( $default_leeway ) { return 120; } );
+```
+
+This would provide a 120 second leeway. You may need to adjust this depending upon how skewed your server's time is.
+
+## I see the error message "This account does not have an email associated..." that prevents me from logging in
+
+If you get this error, make sure you are requesting an email from each provider in the Auth0 Dashboard under Connections -> Social (expand each provider). Take into account that not all providers return email addresses for users (e.g., Twitter). If this happens, you can always add an Email address to any logged in user through the Auth0 Dashboard (or API). See Users -> Edit.
+
+For Connections that don't provide an `email_verified` flag (some Enterprise connections will not include this) *or* to skip this validation for specific Social Connections, add the strategy for that Connection in the "Skip Strategies" field. This field is located below the **Require Verified Email** switch accessible via **wp-admin** > **Auth0** > **Settings** > **Advanced**.
+
+**This field should only be used if necessary because it circumvents the security precautions recommended Auth0.**
+
+## I see the error message "There is a user with the same email" that prevents me from logging in
+
+This means that there is a user in WordPress that has the same email as the one being used to login associated with a different Auth0 user. If you're in the process of testing the plugin or want to associate the existing user with the new Auth user instead:
+
+1. Log in as an admin
+1. Go to wp-admin > Users and search for the email being used
+1. View the user's profile and scroll down to the bottom
+1. Click **Delete Auth0 Data** and confirm
+
+::: note
+If you have 2 user accounts in Auth0 with the same email address, this error message will persist. We recommend looking into [user account linking](/users/concepts/overview-user-account-linking).
+:::
+
+## I see the error message "Failed cross origin authentication" or "No verifier returned from client" in my browser's console logs when trying to log in
+
+Check your "Allowed Callback URLs" and "Allowed Origins (CORS)" fields in the [Application](${manage_url}/#/applications) settings for your WordPress site to make sure those are correct. If you're using a Chromium-based browser, see [Cross-Origin Authentication](/cross-origin-authentication#limitations) to make sure you don't have third-party cookies turned off.
+
+## I need to rerun the Setup Wizard, but I don't see that menu option anymore.
+
+This means that the plugin is already configured with a Domain, Client ID, and Client Secret. Running the Setup Wizard a second time can have unpredictable results. If you're setting up WordPress for the first time and want to start over before any logins have occurred:
+
+1. Go to **wp-admin** > **Auth0** > **Settings** > **Basic**.
+1. Delete the Domain and Client ID. Scroll down and click **Save Changes**.
+1. Go to [Auth0 Dashboard > Applications](${manage_url}/#/applications)
+1. Find the Application that was created by WordPress (its name should be the site name of your WordPress site)
+1. Click on the Application to view its settings. Scroll to the bottom of the screen and click the **Delete Application** button.
+1. Go to the [Auth0 Dashboard > Connections > Database](${manage_url}/#/connections/database)
+1. Find the Connection that was created by WordPress (its name should be the site name of your WordPress site prepended with "DB-")
+1. Click on the Connection to view the settings. Scroll down to the bottom, and click **I Want To Delete This Connection*. ***Please note that this will delete the Connection and all users that were created within.***
+1. Return to WordPress. You will now see the Setup Wizard option under Auth0 in the admin menu.
+
+## How do I setup Passwordless login?
+
+Passwordless login is possible any Auth0-enabled website using email or SMS. To make this work on your WordPress site:
+
+1. Turn on "Passwordless Login" from the plugin settings' **Features** tab and save
+2. In your Auth0 dashboard, go to **[Connections > Passwordless](${manage_url}/#/connections/passwordless)**
+ - To use email, turn on the **Email** connection and modify the settings if desired. This will turn on email code login (users are emailed a code which is then typed into the login form on your site).
+ - To use a "magic link" (emailed link will automatically log users in), add `{passwordlessMethod: 'code'}` to the "Extra Settings" field in the plugin settings' **Advanced** tab.
+ - To use SMS login, turn on the **SMS** connection and follow the steps to set up a Twilio developer account (this will require a paid Twilio account depending on usage).
-## My configuration is wrong and I can't authenticate using Auth0. Is there another way to access the plugin?
+The Auth0 login form will select a Passwordless method depending on which connection is activated above. If you have both connections active, it will default to email. In this case, either turn off the email connection to show SMS or add `sms` to the **Connections** field in the plugin settings' **Advanced** tab.
-The plugin can be accessed using valid WordPress credentials through the regular WordPress login by adding `?wle` to the login url. For example: `http://yourdomain.com/wp-login.php?wle`.
+## I have two accounts for the same user in WordPress
+
+Under some situations, you may end up with a user with two accounts. WordPress allows you to merge users by deleting one of the accounts and attributing that account's content to another user. Go to wp-admin > Users, select the account you want to remove, and in the confirmation dialog select another user to transfer the content.
+
+## My configuration is wrong, and I can't authenticate using Auth0. Is there another way to access the plugin?
+
+The plugin can be accessed using valid WordPress credentials through the regular WordPress login by adding `?wle` to the login URL. For example: `http://yourdomain.com/wp-login.php?wle`.
## I am having problems when a user logs in. Where can I find a log of what is happening?
-The plugin provides an error log where you can check what has happened. Access it through the **Error Log** sub-item of the **Auth0** plugin menu.
+The plugin provides an error log where you can check what has happened. Access it through the **Error Log** sub-item of the **Auth0** plugin menu. The [logs](${manage_url}/#/logs) in your Auth0 dashboard can also provide additional information.
-## How can I show the widget or shortcode in signup mode as default?
+## How can I show the widget or shortcode in signup mode by default?
-You can use the widget `Extra configuration` setting (or the `extra_conf` attribute in the shortcode) and add this json `{"mode":"signup" }` that will force the plugin to be shown in this mode.
+You can use the widget `Extra configuration` setting (or the `extra_conf` attribute in the shortcode) and add this JSON `{"mode":"signup" }` that will force the plugin to be shown in this mode.
-## When using a plugin to force the login, the user is not logged in.
+## When using a plugin to force the login, the user is not logged in
-Be sure to **whitelist** the Auth0 `callback_url`.
+This is typically caused by a cached page after login. Check with your host for strategies to mitigate this or try adding a cache-busting parameter to the URL ([see this Gist for instructions](https://gist.github.com/joshcanhelp/e3eb693749f0fe66aad097c3bbb3b415)).
-### The user is not logged in when using the `wp-force-login` plugin.
+### The user is not logged in when using the "Force Login" plugin
This is because the callback URL has not been whitelisted. Try adding this code to the `my_forcelogin_whitelist` filter:
```php
-function my_forcelogin_whitelist( $whitelist ) {
-
-...
-
- if( $_GET['auth0'] == 1 ) {
+function wp_auth0_forcelogin_whitelist( $whitelist ) {
+ if ( ! empty( $_GET['auth0'] ) ) {
$whitelist[] = site_url($_SERVER['REQUEST_URI']);
}
-
-...
-
return $whitelist;
}
-add_filter('v_forcelogin_whitelist', 'my_forcelogin_whitelist', 10, 1);
+add_filter('v_forcelogin_whitelist', 'wp_auth0_forcelogin_whitelist', 10, 1);
```
-## How can I redirect the users to a certain URL after login?
+## How can I redirect the users to a specific URL after login?
+
+::: note
+All redirects are checked using `wp_safe_redirect()` before being performed. If you're trying to redirect to a domain that is not your main domain, add that domain to the check using the core WordPress `allowed_redirect_hosts` filter ([documentation](https://developer.wordpress.org/reference/hooks/allowed_redirect_hosts/)).
+:::
### On the login page
-This plugin leverages WordPress features to work seamless with default settings. To add a redirect, you can append the `redirect_to` query parameter to the URL when you direct the user to the login page. The plugin will redirect the user to this URL after a successful login.
+This plugin leverages WordPress features to work seamlessly with default settings. To add a redirect, you can append the `redirect_to` query parameter to the URL when you direct the user to the login page. The plugin will redirect the user to this URL after a successful login.
You can also use the **Login redirection URL** setting in the Auth0 plugin settings page. This will URL be used to redirect the user when the `redirect_to` parameter is not provided.
@@ -74,9 +146,9 @@ The shortcode will automatically redirect to the same page where the user was be
## How can I migrate my WordPress users to Auth0?
-The current version of the plugin does not provide a way to automatically migrate users to Auth0, but you have a few options:
+The current version of the plugin does not provide a way to migrate users to Auth0 automatically, but you have a few options:
-- The plugin exposes two endpoints to mark your custom database connection for **import to Auth0** mode as described in [Import users to Auth0](/connections/database/migrating). You can use these [plugin scripts](https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_CustomDBLib.php) to setup your connection.
+- The plugin exposes two endpoints to mark your custom database connection for **import to Auth0** mode as described in [Import users to Auth0](/connections/database/migrating). You can use these [plugin scripts](https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_CustomDBLib.php) to set up your connection.
- Export your user data to a JSON file and upload it for batch-import into Auth0. Initially, your users will have to reset their passwords when logging in using Auth0 because there is no way for Auth0 to decrypt the WordPress passwords during migration. To generate the JSON file, follow the instructions at [Mass-importing users to Auth0](/bulk-import). Then you will need to upload the file using the [Import users](/api/v2#!/Jobs/post_users_imports) endpoint.
@@ -84,9 +156,9 @@ The current version of the plugin does not provide a way to automatically migrat
## The form_title setting is ignored when I set up the dict setting
-Internally, the plugin uses the dict setting to change the Auth0 widget title. When you set up the dict field it overrides the form_title one.
+Internally, the plugin uses the dict setting to change the Auth0 widget title. When you set up the dict field, it overrides the form_title one.
-To change the form_title in this case, you need to add the following attribute to the dict json:
+To change the form_title in this case, you need to add the following attribute to the dict JSON:
```json
{
@@ -96,25 +168,66 @@ To change the form_title in this case, you need to add the following attribute t
}
```
-## How can I configure Lock settings that are not provided in the settings page?
+## How can I modify the embedded Auth0 login form?
-There is a field called "Extra settings" that allows you to add a json object with all the settings you want to
-configure.
+There are many options on the **Appearance** tab of the plugin settings page that can change the look and feel of the login form that is embedded on your site (`wp-login/php` page, shortcodes, or widgets). These options are covered on the [Configuration page](/cms/wordpress/configuration#appearance). This will not affect the the login form on the Auth0-hosted Universal Login Page.
-Have in mind that all the "Extra settings" that we allow to set up in the plugin settings page will be overridden.
+There is also a field called "Extra Settings" on the **Advanced** tab that accepts a valid JSON object with all the settings you want to configure. This will override any changes made on the **Appearance** tab. For all the possible configuration options, please see our [documentation](/libraries/lock/v11/configuration).
-## Database migration does not work
-
-Your server needs to allow inbound connections from Auth0.
+To use custom styling or JavaScript with the embedded Auth0 login form, please see our [documentation here](https://auth0.com/docs/libraries/lock/v11/ui-customization#overriding-css). External style sheets and JS files should be loaded in your theme using the [`wp_enqueue_scripts`](https://developer.wordpress.org/reference/hooks/wp_enqueue_scripts/) hook for shortcodes/widgets and the [`login_enqueue_scripts`](https://developer.wordpress.org/reference/hooks/login_enqueue_scripts/) hook for `wp-login.php`.
## The session expires too soon
-The Auth0 plugin does not handle sessions, it uses the WordPress settings. By default, user sessions are kept alive for 2 days. You can enable the `Remember users session` setting to allow sessions to remain live for up to 14 hours.
+The Auth0 plugin does not handle sessions; it uses the WordPress settings. By default, user sessions are kept alive for two days. You can enable the `Remember users session` setting on the plugin settings' **Advanced** tab to allow sessions to remain live for up to 14 hours.
+
+## How do I implement a Refresh Token?
+
+We implemented additional parameters in the login methods used by the plugin to allow for Refresh Tokens. Use the [`auth0_auth_scope`](/cms/wordpress/extending#auth0_auth_scope) filter combined with the [`auth0_user_login`](/cms/wordpress/extending#auth0_user_login) action to accomplish this.
+
+## Profile data saved in WordPress is not being synced to the Auth0 user account.
+
+This is a current limitation of the plugin but something we're looking at in a future release. The one exception to this is the user password. If the password is changed in WordPress and it passes the security policy set for the database connection being used, then that password will update for the Auth0 user as well. We'll be adding an error message in a future release to stop the process if the password is not strong enough.
+
+## How do I migrate from "Social Login with Auth0" to "Login by Auth0"?
+
+Historically, Auth0 has maintained two WordPress plugins:
+
+- [Login by Auth0](https://wordpress.org/plugins/auth0/)
+- [Social Login with Auth0](https://wordpress.org/plugins/social-login-with-auth0/)
+
+These two plugins are effectively the same, but **Social Login with Auth** will not receive any updates past version 3.7.0 (released 13 August 2018). Migrating from **Social Login with Auth** to **Login by Auth0** is simple and won't result in any Auth0 or WordPress data loss.
::: note
-This plugin leverages WordPress session handling and uses [wp_set_auth_cookie()](https://developer.wordpress.org/reference/functions/wp_set_auth_cookie/) to create the session cookie. This setting will send `true` as a second parameter to allow the session to last longer.
+Moving from **Social Login with Auth** to **Login by Auth0** will update the version number you see, so make sure to test this change out on a staging or development server first (just as you would if you were updating the plugin in wp-admin). Furthermore, logins may not work during the migration process, so be sure to use a maintenance mode plugin or complete the migration during off-peak hours.
:::
+The easiest way to migrate is via (S)FTP:
+
+1. Log in to the WordPress site as an administrator.
+1. [Download Login by Auth0](https://downloads.wordpress.org/plugin/auth0.zip) and unzip it locally.
+1. Deactivate the **Social Login with Auth0** plugin from the WordPress admin > Plugins screen.
+1. Log in to the server you want to migrate to and navigate to `wp-content/plugins`.
+1. Move the `social-login-with-auth0` folder out of the plugins folder to back up the contents.
+1. Upload the new `auth0` plugin folder to the plugins directory.
+1. Activate the new "Login by Auth0" plugin from the WordPress **Admin** > **Plugins** screen.
+
+If you're unable to access the site via FTP, you can also run the process directly from the WordPress admin:
+
+1. Log in to the WordPress site as an administrator.
+1. Go to **Auth0** > **Import-Export Settings**.
+1. Click **Export Settings**, then **Export**.
+1. Deactivate the **Social Login with Auth0** plugin from the WordPress **Admin** > **Plugins** screen.
+1. Delete the **Social Login with Auth0** plugin and confirm.
+1. Go to **Plugins** > **Add New** and search for "Auth0".
+1. For the **Login by Auth0** plugin (make sure to check the name), click **Install Now**.
+1. When this completes, click **Activate**.
+1. Check **Auth0** > **Settings** and make sure the previous settings remain. If not:
+ 1. Go to **Auth0** > **Import-Export Settings**.
+ 1. Paste in the settings JSON exported previously and click **Import**.
+1. Completely delete the settings file export JSON (it contains sensitive information).
+
+Everything should now be working as expected with the new plugin and updates will resume as usual.
+
## Keep Reading
More information on the Login by Auth0 WordPress plugin:
@@ -123,6 +236,5 @@ More information on the Login by Auth0 WordPress plugin:
* [How does it work?](/cms/wordpress/how-does-it-work)
* [Install the plugin](/cms/wordpress/installation)
* [Configure the plugin](/cms/wordpress/configuration)
-* [JWT API authentication](/cms/wordpress/jwt-authentication)
* [Extend the plugin](/cms/wordpress/extending)
:::
diff --git a/articles/cms/wordpress/user-migration.md b/articles/cms/wordpress/user-migration.md
new file mode 100644
index 0000000000..ec221f0d38
--- /dev/null
+++ b/articles/cms/wordpress/user-migration.md
@@ -0,0 +1,161 @@
+---
+description: This page explains the user migration feature of the Login by Auth0 WordPress Plugin
+toc: true
+topics:
+ - wordpress
+ - cms
+---
+# User Migration in Login by Auth0
+
+The User Migration functionality uses a core Auth0 feature, [Custom Databases](https://auth0.com/docs/connections/database/custom-db), combined with URL endpoints in the Login by Auth0 plugin to allow users to authenticate with existing WordPress user accounts.
+
+## How It Works
+
+When you enable data migration, the plugin exposes two secure endpoints that allow Auth0 to authenticate users using WordPress accounts. These endpoints are secured with a secret token and can be set only to allow IP addresses used by Auth0.
+
+The login flow is as follows:
+
+1. A user attempts to login with an Auth0 login form (embedded on your site or hosted at Auth0).
+2. If Auth0 can't find a user associated with the provided credentials in your database connection, it proceeds to call the migration endpoint on your WordPress site with the user credentials and the migration token.
+3. The plugin finds a user in your WordPress database with the provided username/email and verifies the password.
+4. If a user can be successfully authenticated, Auth0 creates the user in the database connection for your site, authenticates the user, and logs them in.
+5. The next time the user logs in, they will use the Auth0 user, and the migration endpoint will be skipped.
+
+User Migration must be set up when the site is first connected to Auth0. Attempting to turn on or off custom database scripts for a database connection that has already had users will fail. See the **Troubleshooting** section for more information about moving between modes.
+
+## Setup and Configuration
+
+The easiest way to setup User Migration is to use the Setup Wizard when the plugin is first installed. [That process is described here](https://auth0.com/docs/cms/wordpress/installation#option-2-user-migration-setup).
+
+If the User Migration Setup Wizard could not complete or you want to see the process in more detail, follow the steps below. Again, this is starting from scratch with a database connection that does not have any users. The following process should be completed on a site with no traffic or with maintenance mode turned on.
+
+1. Make sure you have an Application [created and configured correctly](https://auth0.com/docs/cms/wordpress/configuration#application-setup) and an empty Database Connection [created and activated for the Application](https://auth0.com/docs/cms/wordpress/configuration#database-connection-setup). These can be the same as the ones created in the [Standard Setup Wizard process](https://auth0.com/docs/cms/wordpress/installation#option-1-standard-setup) or created from scratch.
+2. In the **Auth0 > Settings** screen in WordPress, make sure the Application's Domain, Client ID and Client Secret are saved in the correct fields in the **Basic** tab.
+3. On the **Advanced** tab, turn on the "User Migration Endpoints" setting and click **Save Changes**. If you are using [constant-based settings](https://auth0.com/docs/cms/wordpress/configuration#php-constant-setting-storage), set `AUTH0_ENV_MIGRATION_WS` to `true` and `AUTH0_ENV_MIGRATION_TOKEN` to a secure random string at least 16 digits long and without single quotes or backslashes.
+4. Under the settings, you should now see a **Security Token**. Keep this page open as you will need this value later on in the process.
+5. In the Auth0 Dashboard, go to the Database Connection you want to use and turn on **Requires Username** and **Import Users to Auth0**.
+6. Now click the **Custom Database** tab and turn on **Use my own database**
+7. There should be two tabs below this setting under the "Database Action Scripts" heading, one for **Login** and one for **Get User**
+8. Click on the **Login** tab
+9. Clear out all the existing code, open [this link](https://raw.githubusercontent.com/auth0/wp-auth0/master/lib/scripts-js/db-login.js) in a new tab, copy all the code there, and paste it into the code editor back in Auth0.
+10. **This step is for versions 3.10.0 and earlier:** Look for `{THE_WS_URL}` and replace that with your WordPress instance's site URL, followed by `/index.php?a0_action=migration-ws-login`. The site URL can be found in the **Settings > General** screen in wp-admin. You can test this by pasting the complete URL in your browser. You should see `{"status":401,"error":"Unauthorized"}`.
+11. **This step is for versions 3.10.0 and earlier:** Look for `{THE_WS_TOKEN}` and replace that with the token that appears under the "User Migration Endpoints" setting.
+12. There should be no errors in the editor. If everything looks good, click **Save** at the top.
+13. **This step is for 3.11.0 and later:** Scroll down to **Settings** and add the following configuration variables:
+ - `endpointUrl` set to your WordPress instance's site URL (**wp-admin > Settings > General >** "Site URL" field), followed by `/index.php?a0_action=`.
+ - `migrationToken` set to the security token value seen in step 4 above.
+ - `userNamespace` set to your Application name in Auth0 or any other value only including letters, numbers, and dashes.
+
+
+
+14. Click the **Try** button at the top and use a valid WordPress user account in the form that appears. You should see the "The profile is" followed by the user's data. If not, please see the [**Troubleshooting**](#troubleshooting) section below.
+15. Now click on the **Get User** tab, clear out all the existing code, open [this link](https://raw.githubusercontent.com/auth0/wp-auth0/master/lib/scripts-js/db-get-user.js) in a new tab, copy all the code there, and paste it into the code editor back in Auth0.
+16. **This step is for 3.10.0 and earlier:** Look for `{THE_WS_URL}` and replace that with your WordPress instance's site URL, followed by `/index.php?a0_action=migration-ws-get-user`. The site URL can be found in the **Settings > General** screen in wp-admin. You can test this by pasting the complete URL in your browser. You should see `{"status":401,"error":"Unauthorized"}`.
+17. **This step is for 3.10.0 and earlier:** Look for `{THE_WS_TOKEN}` and replace that with the token that appears under the "User Migration Endpoints" setting.
+18. There should be no errors in the editor. If everything looks good, click **Save** at the top.
+19. Click the **Try** button at the top and use an email with a valid WordPress user account in the form that appears. You should see the "The profile is" followed by the user's data. If not, please see the [**Troubleshooting**](#troubleshooting) section below.
+20. In a new browser session, navigate to a login page on the WordPress site and attempt to login (the user should not already exist in the database). You'll notice that the login process takes a little longer than usual at first but should succeed. Subsequent logins will be faster.
+21. (OPTIONAL) To turn on additional security for the migration endpoints, go to **Auth0 > Settings** screen in WordPress, turn on "Migration IPs Whitelist," and then **Save Changes**. Attempt to log in with a different user to test that Auth0 can still reach the endpoints.
+
+At this point, the User Migration setup is complete, and existing WordPress users will be trickle migrated to the Auth0 Database Connection.
+
+## Troubleshooting
+
+Issues with the User Migration typically come from a few places:
+
+- Incorrect URL or token in the custom database scripts.
+- IP whitelist turned on but with incorrect IP addresses.
+- Restricted or cached endpoints on your WordPress instance.
+
+The best way to start troubleshooting the issue is to use the **Try** button for the **Login** script found in the Custom Database tab of the Database Connection being used on [Auth0 Dashboard > Connections > Database Connections](${manage_url}/#/connections/database). The following are the error messages you might see and the steps to take to fix.
+
+### "Unexpected token < in JSON at position 0"
+
+This means the custom script is not getting data back in a format it can use. An incorrect endpoint URL likely causes this in the database script.
+
+First, copy the URL on line 10 in the script and paste it in your browser. If the endpoint is correct, it should display one of the two messages below:
+
+```
+{"status":401,"error":"Unauthorized"}
+
+// or
+
+{"status":403,"error":"Forbidden"}
+```
+
+If what you're seeing is the home page or a 404, then the URL is incorrect. Look for your site URL under **Settings > General > Site URL** in the WordPress admin. Add `/index.php?a0_action=migration-ws-login` to the end for the Login script and `/index.php?a0_action=migration-ws-get-user` to the end for the Get User script.
+
+- **For versions 3.10.0 and earlier**: The URL value should appear in the script itself as the first parameter in the `request.post` call.
+- **For versions 3.11.0 and later**: The token value should be saved in a configuration variable. Add the following to the first line of the function and use the **Try** button to see what is stored for `endpointUrl`:
+
+```js
+callback(null, configuration);
+```
+
+If you're sure the URLs are correct and are still having this issue, check with your host to make sure those URLs are not cached or restricted in any way.
+
+### "Wrong email or password"
+
+This is the default error shown if anything else goes wrong. The easiest way to troubleshoot what's happening is to temporarily output the error that's being sent back (these are opaque by default to avoid displaying anything that might give attackers something to work with).
+
+On line 30 of the Login script, change:
+
+```js
+callback(null);
+```
+
+... to:
+
+```js
+callback(wpUser.error);
+```
+
+... save the script, and try the connection again. You should see one of the following messages and be able to pinpoint the issue with the steps below. Once you've solved the issue, change the script back to what it was.
+
+#### "Forbidden"
+
+This means that the migration endpoints are turned off in your WordPress install. Go to **Auth0 > Settings > Advanced** and turn on the "User Migration Endpoints" setting. Make sure the token that appears there is the same as what is used for both custom database scripts:
+
+- **For versions 3.10.0 and earlier**: The token value should appear in the script itself after `access_token:`
+- **For versions 3.11.0 and later**: The token value should be saved in a configuration variable. Add the following to the first line of the function and use the **Try** button to see what is stored for `migrationToken`:
+
+```js
+callback(null, configuration);
+```
+
+#### "Unauthorized"
+
+This means that the migration IP whitelist is turned on, but the incoming IP address is not on the list. Just below the Login script you should see a list of IP addresses:
+
+
+
+Make sure all of those IP addresses appear below the "Migration IPs Whitelist" field under **Auth0 > Settings > Advanced** in the plugin:
+
+
+
+If one or more of the IP addresses listed in Auth0 do not appear in WordPress, add the missing ones into the field and save the settings page. Also, please post in the Auth0 [Community](https://community.auth0.com/tags/wordpress) (tagged `wordpress`) with the missing IP address(es), so we can address the issue.
+
+#### "Unauthorized: missing authorization header"
+
+The security token is either missing in the database script (line 16), or your server is not processing the headers correctly. Check the Login script and make sure that the token exists and matches what is in WordPress. If the token is there and correct, then you'll need to talk to your host to enable the `Authorization` header to be parsed. See [this StackOverflow thread](https://stackoverflow.com/questions/17018586/apache-2-4-php-fpm-and-authorization-headers) for server troubleshooting and use [the plugin code](https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_Routes.php#L138) as a reference for how the token is retrieved.
+
+#### "Invalid token"
+
+The security token in the database script is incorrect. Check the Login script line 16 and make sure that the token matches what is in WordPress.
+
+#### "Invalid Credentials"
+
+The email address and/or password being used is incorrect. Check to make sure you're entering the correct email address and that the password is correct. You can reset the user password to something else to make sure you have the correct one.
+
+### Cannot Change Email or Incorrect User Data
+
+If you are using more than one custom database connection in your Auth0 tenant and you're unable to change the email address or are getting user data stored for the wrong user, it's likely that you have overlapping user IDs in Auth0. This problem has been fixed for new sites installing 3.11.0 but, for connections created before then, this will need to be manually fixed by doing one of the following:
+
+* If you don’t have any user data stored that needs to be kept (if you’re only using the connection to support login and not storing any metadata), you can create a new custom database connection using the steps above (using the 3.11.0 notes) and switch the Application to this new connection (make sure to turn the old connection off). The migration will be restarted, and there will be no impact on the user experience.
+* If you do have data in Auth0 that needs to be kept, you can use our [User Import/Export Extension](/extensions/user-import-export) to adjust the user data.
+ 1. Create a new custom database connection using the steps above (using the 3.11.0 notes).
+ 2. Export all users from the existing connection (we recommend putting your site in maintenance mode while doing the switch-over, so no users are missed).
+ 3. Change all user IDs to add the namespace used when creating the new connection. User IDs should go from something like `auth0|123` to `auth0|Your-WP-Site-Name|123`. Adjust all other fields you need to follow the [import schema](/users/references/bulk-import-database-schema-examples).
+ 4. Turn the new connection on and the old connection off for your application.
+ 5. Import the new user data into the new connection and test.
+* If you have a paid account, you can contact our support team to run a database update script to change the user IDs to a namespaced version and add the namespace to your database script at the same time (step 12 in [Setup and Configuration](#setup-and-configuration) above).
diff --git a/articles/compliance/gdpr/data-processing.md b/articles/compliance/gdpr/data-processing.md
index b1feb7780a..b26cd5e768 100644
--- a/articles/compliance/gdpr/data-processing.md
+++ b/articles/compliance/gdpr/data-processing.md
@@ -1,6 +1,11 @@
---
title: Auth0 Data Processing
description: How Auth0 processes data in its possession
+topics:
+ - compliance
+ - gdpr
+contentType: concept
+useCase: compliance
---
# Auth0 Data Processing
@@ -10,7 +15,7 @@ This document discusses what data Auth0 has, as well as how it processes this da
All of the data Auth0 has about an end user is located in the Auth0 user profile. The specific attributes contained in the user profile vary based on customer implementation and are based on a number of factors, such as connection type, user consent during the authentication flow, and whether you've augmented the user profiles with additional information.
-## Where Auth0 Data is Stored
+## When Auth0 Data is Stored
The Auth0 user profile information is stored in Auth0 when you use a database connection. If a user logs in using any other type of connection (including custom database connections), Auth0 stores information provided by the external identity provider for future queries.
diff --git a/articles/compliance/gdpr/definitions.md b/articles/compliance/gdpr/definitions.md
index b0875ed08d..5acd82b904 100644
--- a/articles/compliance/gdpr/definitions.md
+++ b/articles/compliance/gdpr/definitions.md
@@ -1,6 +1,11 @@
---
title: General Data Protection Regulation (GDPR) Definitions
description: Definitions used for Auth0's documentation on GDPR
+topics:
+ - compliance
+ - gdpr
+contentType: reference
+useCase: compliance
---
# Definitions
diff --git a/articles/compliance/gdpr/features-aiding-compliance/_encrypt-data.md b/articles/compliance/gdpr/features-aiding-compliance/_encrypt-data.md
index e6fdf3daee..55566bda13 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/_encrypt-data.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/_encrypt-data.md
@@ -26,6 +26,7 @@ For example, to save the encrypted `passportNumber` in the user's profile, send
}
```
-:::note
+::: note
Replace the `YOUR_ACCESS_TOKEN` placeholder with a token that will allow you to access this endpoint. This should be a [Management API Token](/api/management/v2/tokens), with the scopes `update:users` and `update:users_app_metadata`.
:::
+
diff --git a/articles/compliance/gdpr/features-aiding-compliance/data-minimization.md b/articles/compliance/gdpr/features-aiding-compliance/data-minimization.md
index 4eb74b47c8..26405dc51e 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/data-minimization.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/data-minimization.md
@@ -2,6 +2,11 @@
title: "GDPR: Data Minimization"
description: This article discusses how customers can minimize the personal data they collect for processing and ensure their security
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType: how-to
+useCase: compliance
---
# GDPR: Data Minimization
@@ -16,8 +21,8 @@ There are several Auth0 features than can help you achieve these goals, like acc
To limit the amount of personal information in the Auth0 user profile, you can:
- Minimize (or avoid) saving personal information in the metadata section of the user profile
-- If you use [enterprise directories](/identityproviders#enterprise), configure them to return only the minimum information needed
-- If you use [social providers](/identityproviders#social), configure them to return only the minimum information needed
+- If you use [enterprise directories](/connections/identity-providers-enterprise), configure them to return only the minimum information needed
+- If you use [social providers](/connections/identity-providers-social), configure them to return only the minimum information needed
- [Blacklist the user attributes](/security/blacklisting-attributes) that you do not want to persist in the Auth0 databases
## Encrypt user profile information
@@ -26,7 +31,7 @@ To limit the amount of personal information in the Auth0 user profile, you can:
## Use account linking
-Every time a user uses a connection to log in to your application, a user profile is created if it doeasn't already exist. Note that this is per connection.
+Every time a user uses a connection to log in to your application, a user profile is created if it doesn't already exist. Note that this is per connection.
To better understand this, consider the following scenario. Your application offers three different options for signup:
- sign up with email/password
@@ -35,12 +40,12 @@ To better understand this, consider the following scenario. Your application off
If a user signs up with Google, this will create a user profile in Auth0. If the same user, upon return, does not remember what he signed up with, and chooses to login with Facebook, Auth0 will create another user profile for the user. So now you have two profiles for the same user.
-You can fix this with [account linking](/link-accounts). You can link multiple accounts under a single user profile, regardless of the connection's type (for example, user/password, social, or SAML).
+You can fix this with [account linking](/users/concepts/overview-user-account-linking). You can link multiple accounts under a single user profile, regardless of the connection's type (for example, user/password, social, or SAML).
-There are three ways to implement this:
-- **Automatic** account linking: you can configure a rule that will link accounts with the same email address. For more info and a sample rule, see [Automatic Account Linking](/link-accounts#automatic-account-linking)
-- **User-initiated** account linking: your app must provide the UI so an authenticated user can link their accounts manually. For a sample implementation, see [User Initiated Account Linking](/link-accounts/user-initiated-linking)
-- **Suggested** account linking: in this case you still configure a rule that will link accounts with the same verified e-mail address. However, instead of completing the link automatically, your app will first prompt the user to link their identities. For a sample implementation, see [Account Linking using server side code](/link-accounts/suggested-linking)
+There are two ways to implement this:
+
+- **User-initiated** account linking: your app must provide the UI so an authenticated user can link their accounts manually. For a sample implementation, see [Link User Accounts Server-Side Scenario](/users/references/link-accounts-user-initiated-scenario)
+- **Suggested** account linking: in this case you still configure a rule that will link accounts with the same verified email address. However, instead of completing the link automatically, your app will first prompt the user to link their identities. For a sample implementation, see [Link User Accounts Server-Side Scenario](/users/references/link-accounts-server-side-scenario)
## Export logs
@@ -58,7 +63,7 @@ You can provide search criteria using the **q** parameter and retrieve specific
To access the API, you need a [Management APIv2 token](/api/management/v2/tokens).
-This sample request retrieves all logs for successful logins (the event acronym for successful login is `s`). The list of fields we will retrieve per log entry is: **date**, **escription**, **client_id**, and **log_id**.
+This sample request retrieves all logs for successful logins (the event acronym for successful login is `s`). The list of fields we will retrieve per log entry is: **date**, **description**, **client_id**, and **log_id**.
```har
{
diff --git a/articles/compliance/gdpr/features-aiding-compliance/data-portability.md b/articles/compliance/gdpr/features-aiding-compliance/data-portability.md
index a8fb492e77..9494372ef5 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/data-portability.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/data-portability.md
@@ -2,6 +2,11 @@
title: "GDPR: Data Portability"
description: This article discusses how customers can export user data in order to comply with data portability GDPR requirements
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType: how-to
+useCase: compliance
---
# GDPR: Data Portability
@@ -23,4 +28,4 @@ To export a user's data manually from the Dashboard:
## Export data using the API
-You can export a user's full profile using our Management API. The response will be in JSON format. You can either [search for a user using their ID](/users/search/best-practices#users-by-id), or [export a list of your users](/users/search/best-practices#user-export).
+You can export a user's full profile using our Management API. The response will be in JSON format. You can either [search for a user using their ID](/best-practices/search-best-practices#users-by-id), or [export a list of your users](/best-practices/search-best-practices#user-export).
diff --git a/articles/compliance/gdpr/features-aiding-compliance/index.md b/articles/compliance/gdpr/features-aiding-compliance/index.md
index 60fb656092..ec4b898cf5 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/index.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/index.md
@@ -2,6 +2,13 @@
title: "How Auth0 can help with GDPR"
description: This article discusses the Auth0 features that can help customers comply with GDPR requirements
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType:
+ - concept
+ - index
+useCase: compliance
---
# How Auth0 Can Help With GDPR Compliance
diff --git a/articles/compliance/gdpr/features-aiding-compliance/protect-user-data.md b/articles/compliance/gdpr/features-aiding-compliance/protect-user-data.md
index f2e12cf7d4..880ffc78d8 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/protect-user-data.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/protect-user-data.md
@@ -2,6 +2,11 @@
title: "GDPR: Protect and secure user data"
description: This article discusses how customers can use Auth0 to better protect and secure their user's personal data
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType: concept
+useCase: compliance
---
# GDPR: Protect and secure user data
@@ -21,16 +26,28 @@ There are several Auth0 features than can help you achieve that, like user profi
## Enable brute-force protection
-You can enable the brute-force protection shield in order to stop malicious attempts to access your application.
+Auth0's brute-force protection shield is enabled by default to stop malicious attempts to access your application.
+
+There are two types of triggers for this shield:
+
+* 10 consecutive failed login attempts for the same user and from the same IP address
+* 100 failed login attempts from the same IP address in 24 hours *or* 50 sign up attempts per minute from the same IP address
+
+For example, if a user with *user_id1* signs in from *IP1* and fails to login consecutively for 10 attempts, their log in attempt from this *IP1* will be blocked. Another user, *user_id2*, signing in from *IP1* will not be blocked.
Every time Auth0 detects 10 failed login attempts into a single account from the same IP, we will:
-- Send a notification email to the user
-- Block the suspicious IP address
+- Send a notification email to the user.
+- Block the suspicious IP address for that user.
+
+Every time Auth0 detects 100 failed login attempts in 24 hours or 50 sign up attempts from the same IP address, we will:
+
+- Notify dashboard administrator(s).
+- Block suspicious addresses for 15 minutes.
You can enable brute-force protection, configure which actions you want to take, and customize the blocked account email using the Dashboard.
-For more information and configuration steps, see [Brute Force Protection](/anomaly-detection#brute-force-protection).
+For more information, see [Brute Force Protection](/anomaly-detection#brute-force-protection).
## Enable breached password detection
@@ -46,13 +63,13 @@ You can enable breached password detection and configure which actions you want
For more information and steps to follow, see [Breached Password Detection](/anomaly-detection#breached-password-detection).
-## Harden your security with multifactor authentication
+## Harden your security with multi-factor authentication
-With mutifactor authentication (MFA), you can add an additional layer of security to your applications. It is a method of verifying a user's identity by asking them to present more than one piece of identifying information.
+With multi-factor authentication (MFA), you can add an additional layer of security to your applications. It is a method of verifying a user's identity by asking them to present more than one piece of identifying information.
-We support MFA using push notifications, SMS, one-time password authentication services, and custom providers. You can enable MFA for specific users or specific actions (for example, access screens with sensitive data). You can also define the conditions that will trigger additional authentication challenges, such as changes in geographic location or logins from unrecognized devices.
+We support MFA using push notifications, SMS, Voice, one-time password authentication services, and custom providers. You can enable MFA for specific users or specific actions (for example, access to screens with sensitive data). You can also define the conditions that will trigger additional authentication challenges, such as changes in geographic location or logins from unrecognized devices.
-To review all available options and their features, and get implementation details for the one that suits your needs, see [Multifactor Authentication in Auth0](/multifactor-authentication).
+To review all available options and their features, and get implementation details for the one that suits your needs, see [Multi-factor Authentication in Auth0](/mfa).
## Help your users choose better passwords
@@ -66,22 +83,36 @@ For information on how to use them see [Password Strength](/connections/database
## Step-up authentication
-With step-up authentication, applications can ask users to authenticate with a stronger authentication mechanism to access sensitive resources. For example, you may have a banking application which does not require [Multifactor Authentication (MFA)](/multifactor-authentication) to view the accounts basic information, but when users try to transfer money between accounts then they must authenticate with one more factor (for example, a code sent via SMS).
+With step-up authentication, applications can ask users to authenticate with a stronger authentication mechanism to access sensitive resources. For example, you may have a banking application which does not require [Multi-factor Authentication (MFA)](/mfa) to view the accounts basic information, but when users try to transfer money between accounts then they must authenticate with one more factor (for example, a code sent via SMS).
You can check if a user has logged in with MFA by reviewing the contents of their ID Token or Access Token. You can then configure your application to deny access to sensitive resources if the token indicates that the user did not log in with MFA.
-For details see [Step-up Authentication](/multifactor-authentication/developer/step-up-authentication).
+For details see [Step-up Authentication](/mfa/concepts/step-up-authentication).
## Availability and resilience
Auth0 is designed and built as a scalable, highly available, multi-tenant cloud service. We are highly resilient to the failure of any of our components, because we implement redundant components at all levels. We also detect failures rapidly and our failover is very quick.
-We support four deployment models:
-
-- A **multi-tenant cloud service** running on Auth0's cloud
-- A **dedicated cloud service** running on Auth0's cloud
-- A **dedicated cloud service** running on Customer's cloud infrastructure
-- An **on-premises virtual [Private SaaS (PSaaS) Appliance](/appliance)** running on Customer's private environment (for the cases where a public cloud-based solution is not acceptable).
+We support three deployment models:
+
+
+
+
Deployment
+
Description
+
+
+
Public Cloud
+
A multi-tenant cloud service running on Auth0's cloud
+
+
+
Private Cloud
+
A dedicated cloud service running on Auth0's cloud
+
+
+
Managed Private Cloud
+
A dedicated cloud service running on either Auth0's cloud or the customer's AWS cloud infrastructure
+
+
You decide which deployment model works best for you based on your business and security requirements.
diff --git a/articles/compliance/gdpr/features-aiding-compliance/right-to-access-data.md b/articles/compliance/gdpr/features-aiding-compliance/right-to-access-data.md
index 3b21b897f1..5f37b3f90a 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/right-to-access-data.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/right-to-access-data.md
@@ -2,6 +2,11 @@
title: "GDPR: Right to access, correct, and erase data"
description: This article discusses which Auth0 features can help customers comply with the GDPR requirements on the user's right to access, correct, and erase their personal data
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType: concept
+useCase: compliance
---
# GDPR: Right to access, correct, and erase data
@@ -9,7 +14,7 @@ As per articles 15, 16, 17, and 19 of GDPR, users have the right to get a copy o
With Auth0, you can access, edit, and delete user information:
- manually, using the [Dashboard](${manage_url}/#/users), or
-- programatically, using the [Management API](/api/management/v2)
+- programmatically, using the [Management API](/api/management/v2)
<%= include('./_legal-warning.md') %>
@@ -34,9 +39,9 @@ You can also retrieve, edit, and delete user information using our API.
First, pick an endpoint that matches your needs:
-- [Retrieve a user using the ID as search criteria](/users/search/best-practices#users-by-id)
-- [Retrieve a user using the Email as search criteria](/users/search/best-practices#users-by-email)
-- [Export all users to a file using a long running job](/users/search/best-practices#user-export)
+- [Retrieve a user using the ID as search criteria](/best-practices/search-best-practices#users-by-id)
+- [Retrieve a user using the Email as search criteria](/best-practices/search-best-practices#users-by-email)
+- [Export all users to a file using a long running job](/best-practices/search-best-practices#user-export)
- [Update a user](/api/management/v2#!/Users/patch_users_by_id). Note that not all fields are editable (see the next paragraph: [Editable data](#editable-data)). Keep in mind that:
- The properties of the new object will replace the old ones. The **user_metadata** and **app_metadata** fields are an exception to this rule. These properties are merged instead of being replaced, though the merge happens only on the first level.
- If you are updating **email_verified**, **phone_verified**, **username**, or **password**, you must set the **connection** parameter.
@@ -49,7 +54,7 @@ In order to call any of the API's endpoints, you will need an valid Access Token
Each endpoint at the [Management API explorer](/api/management/v2) has a section **Scopes** that lists the scope(s) that the Access Token must contain in order to access it. For example, the [Delete user endpoint](/api/management/v2#!/Users/delete_users_by_id) requires the `delete:users` scope.
:::
-You can [get an Access Token for the Management API manually](/api/management/v2/tokens#get-a-token-manually) or you can [automate the process](/api/management/v2/tokens#automate-the-process).
+To learn more about these tokens and how you can generate one, see [Access Tokens for the Management API](/api/management/v2/tokens).
Once you know which endpoint you want to access, and you have a valid Access Token, you are ready to send your request.
@@ -70,7 +75,7 @@ The following user information can be updated using the API:
- username
::: note
-For a list of all the user attributes, refer to the [Structure of the User Profile](/user-profile/user-profile-structure).
+For a list of all the user attributes, refer to the [Structure of the User Profile](/users/references/user-profile-structure).
:::
The following user information are **not** editable:
@@ -84,7 +89,7 @@ The following user information are **not** editable:
You can search for users using the following:
-- All the [normalized user profile fields](/user-profile/normalized/auth0)
+- All the [normalized user profile fields](/users/normalized/auth0/normalized-user-profile-schema)
- The profile information under the **user_metadata** object:
- name
- nickname
diff --git a/articles/compliance/gdpr/features-aiding-compliance/user-consent/_redirect.md b/articles/compliance/gdpr/features-aiding-compliance/user-consent/_redirect.md
index 373125a9a6..00e39c917a 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/user-consent/_redirect.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/user-consent/_redirect.md
@@ -1,12 +1,10 @@
-For simplicity, we will use this [sample consent form](https://wt-peter-auth0_com-0.run.webtask.io/simple-redirect-rule-consent-form). This is a form we have hosted for you using a [webtask](https://webtask.io/), but later on we will see how to host your own version of this form (with your own URL). You can find the webtask's code at [Auth0 Redirect Rules repo](https://github.com/auth0/rules/blob/master/redirect-rules/simple/webtask.js).
+For simplicity, we will use [this sample consent form](https://github.com/auth0/rules/blob/master/redirect-rules/simple/webtask.js#L31).
-:::note
-If you are implementing this from a regular web app, hosting your own form, then you can also save the consent information at the `user_metadata` using the [Management API's Update User endpoint](/api/management/v2#!/Users/patch_users_by_id).
-:::
+You will need to host this form, and the URL for the form must be publicly-accessible. You'll need to provide the URL where the form can be accessed to Auth0 at a later step of this tutorial.
-1. First, we will add the rule. Go to [Dashboard > Rules](${manage_url}/#/rules) and click **Create Rule**. At the **Rules Templates** select **empty rule**. Change the default rule's name (`empty rule`) to something descriptive, for example `Redirect to consent form`.
+1. Add the [redirect rule](/rules/redirect). Go to [Dashboard > Rules](${manage_url}/#/rules), and click **Create Rule**. At **Rules Templates**, select **empty rule**. Change the default rule's name from `empty rule` to something descriptive (e.g., `Redirect to consent form`).
-1. Add the following JavaScript code and save your changes. The code redirects the user to the `CONSENT_FORM_URL` URL (we will configure this at the next step). Once the user hits **Submit** at the consent form, the rule runs again as part of the callback. At this point we persist the information at the `user_metadata`.
+2. Add the following JavaScript code to the script editor, and **Save** your changes.
```js
function redirectToConsentForm (user, context, callback) {
@@ -23,8 +21,7 @@ If you are implementing this from a regular web app, hosting your own form, then
};
}
- // if user clicked 'I agree' on the consent form, persist it to their profile
- // so they don't get prompted again
+ // if user clicks 'I agree' on the consent form, save it to their profile so they don't get prompted again
if (context.protocol === 'redirect-callback') {
if (context.request.body.confirm === 'yes') {
user.user_metadata = user.user_metadata || {};
@@ -47,15 +44,13 @@ If you are implementing this from a regular web app, hosting your own form, then
}
```
-1. Go back to [Dashboard > Rules](${manage_url}/#/rules), scroll down, and under **Settings**, create a Key/Value pair as follows:
- - **Key**: `CONSENT_FORM_URL`
- - **Value**: `https://wt-peter-auth0_com-0.run.webtask.io/simple-redirect-rule-consent-form`
-
+3. Return to [Dashboard > Rules](${manage_url}/#/rules) and scroll down to the bottom of the page where the **Settings** section is. Create a key/value pair as follows:
-If you want to work with your own implementation of the consent form webtask, you can host your own version of the webtask.js script. For instructions see [Consent Form Setup](https://github.com/auth0/rules/tree/master/redirect-rules/simple#consent-form-setup).
+ - **Key**: `CONSENT_FORM_URL`
+ - **Value**: `your-consent-form-url.com`
-To learn more about redirect rules, see [Redirect Users from Rules](/rules/redirect).
+Be sure to provide the publicly-accessible URL where your consent form can be found.
-:::warning
-If you plan on using this approach in a production environment, make sure to review [Trusted Callback URL's](https://github.com/auth0/rules/tree/master/redirect-rules/simple#trusted-callback-urls) and [Data Integrity](https://github.com/auth0/rules/tree/master/redirect-rules/simple#data-integrity) (both sections address some security concerns).
+::: warning
+When setting up redirection to your consent form for use in a Production environment, be sure to review [Trusted Callback URLs](https://github.com/auth0/rules/tree/master/redirect-rules/simple#trusted-callback-urls) and [Data Integrity](https://github.com/auth0/rules/tree/master/redirect-rules/simple#data-integrity) regarding security concerns.
:::
\ No newline at end of file
diff --git a/articles/compliance/gdpr/features-aiding-compliance/user-consent/index.md b/articles/compliance/gdpr/features-aiding-compliance/user-consent/index.md
index c85be910a1..32129280ed 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/user-consent/index.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/user-consent/index.md
@@ -2,6 +2,13 @@
title: "GDPR: Conditions for Consent"
description: This article discusses which Auth0 features can help customers comply with the Conditions for Consent GDPR requirements
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType:
+ - index
+ - how-to
+useCase: compliance
---
# GDPR: Conditions for Consent
@@ -13,10 +20,10 @@ This article explains how you can use Auth0 features to implement these requirem
## Ask for consent
-Upon signup you have to ask your users for consent. With Auth0, you can save this information at the [user metadata](/metadata). There are several available options here, depending on how you use Auth0 to authenticate your users.
+Upon signup you have to ask your users for consent. With Auth0, you can save this information at the [user metadata](/users/concepts/overview-user-metadata). There are several available options here, depending on how you use Auth0 to authenticate your users.
::: note
-Before you design your solution using metadata make sure you are aware of the restrictions. Auth0 limits the total size of the `user_metadata` to **16 MB**. For more details review the [metadata size limits](/metadata#metadata-size-limits).
+Before you design your solution using metadata make sure you are aware of the restrictions. Auth0 limits the total size of the `user_metadata` to **16 MB**. For more details review the [metadata size limits](/best-practices/metadata-best-practices#metadata-storage-and-size-limits).
:::
### Use Lock
@@ -45,7 +52,7 @@ For a tutorial on how to implement any of these scenarios, see the [Track Consen
### Re-consent and user migration
-If you need to ask for consent from existing users and you decide to migrate your users from an existing database to Auth0, you can use our [Automatic User Migration](/users/migrations/automatic) feature. By activating this, each time a user logs in for the first time (since this was activated), they will be created in Auth0 without having to reset their password.
+If you need to ask for consent from existing users and you decide to migrate your users from an existing database to Auth0, you can use our [Automatic User Migration](/users/guides/configure-automatic-migration) feature. By activating this, each time a user logs in for the first time (since this was activated), they will be created in Auth0 without having to reset their password.
Note that every time your Terms and Conditions change, you **must** ask the users for consent again.
@@ -58,17 +65,17 @@ Note that every time your Terms and Conditions change, you **must** ask the user
According to GDPR, you should be able to show that the user has consented to the processing of their personal data.
-With Auth0 you can save the user's consent information as part of the `user_metadata`. You can either save only a flag, showing if the user has consented or not, or a set of consent information and preferences (including for example, the day the user provided consent, the terms he consented to, etc). Afterwards, you can access and manipilate this information using our Management API.
+With Auth0 you can save the user's consent information as part of the `user_metadata`. You can either save only a flag, showing if the user has consented or not, or a set of consent information and preferences (including for example, the day the user provided consent, the terms he consented to, etc). Afterwards, you can access and manipulate this information using our Management API.
:::note
-To access the Management API you will need an Access Token, for information on how to get one refer to the [Auth0 Management API token](/api/management/v2/tokens).
+To access the Management API you will need an Access Token. For information on how to get one, refer to the [Access Tokens for the Management API](/api/management/v2/tokens).
:::
-The Management API offers several offers several options when it comes to user search and endpoints to update `user_metadata` or batch export users.
+The Management API offers several options when it comes to user search and endpoints to update `user_metadata` or batch export users.
### Search for a user using their email address
-To search for a user using their email address, use [the Search user by email endpoint](/users/search/best-practices#users-by-email).
+To search for a user using their email address, use [the Search user by email endpoint](/best-practices/search-best-practices#users-by-email).
Set the **fields** request parameter to `user_metadata` in order to limit the fields returned. This way, only the user_metadata will be returned instead of the complete user profile.
@@ -115,7 +122,7 @@ Sample response:
### Search for a user using their ID
-To search for a user using their ID, use [the Get a user endpoint](/users/search/best-practices#users-by-id).
+To search for a user using their ID, use [the Get a user endpoint](/best-practices/search-best-practices#users-by-id).
Set the **fields** request parameter to `user_metadata` in order to limit the fields returned. This way, only the `user_metadata` will be returned instead of the complete user profile.
@@ -253,11 +260,11 @@ This will add a new property to the user profile, the **user_metadata.consent.da
### Export consent information
-To export a list of your users using the Management API, use [the User export endpoint](/users/search/best-practices#user-export).
+To export a list of your users using the Management API, use [the User export endpoint](/best-practices/search-best-practices#user-export).
This endpoint creates a job that exports all users associated with a connection. You will need the ID of the connection. To find this ID, use [the Get Connections endpoint](/api/management/v2#!/Connections/get_connections) (you can set the **name** parameter to the name of the connection to retrieve only this one).
-Once you have the connection ID and a [Management API token](/api/management/v2/tokens), you are ready to start exporting users. For a sample request and response see [User Export](/users/search/best-practices#user-export).
+Once you have the connection ID and a [Access Token for the Management API](/api/management/v2/tokens), you are ready to start exporting users. For a sample request and response see [User Export](/best-practices/search-best-practices#user-export).
:::panel What else do I have to do?
- Determine how you want to track consent. We recommend including information on not just the date the user consented, but the version of terms and conditions to which the user agreed. We also recommend including an array to hold information about users that withdraw their permission (remember that the user can consent and withdraw multiple times)
@@ -286,7 +293,7 @@ To delete a user, use the [Delete a user endpoint](/api/management/v2#!/Users/de
}
```
-The response body for this endpoint is empty, so if you want to confirm that the user was successfully deleted try to [retrieve the user using their email](/users/search/best-practices#users-by-email). If the endpoint returns an error, then your call to delete the user was successful.
+The response body for this endpoint is empty, so if you want to confirm that the user was successfully deleted try to [retrieve the user using their email](/best-practices/search-best-practices#users-by-email). If the endpoint returns an error, then your call to delete the user was successful.
### Flag user as deleted
@@ -296,7 +303,7 @@ This allows you to keep a record of deleted users for future use.
#### Step 1: Flag the profile
-To flag a user as deleted use the [app_metadata](/metadata). In the following example, we will show you how to add a property called **deleted** to the **app_metadata** field. This allows you to configure the authentication process to treat all uses with this property set to true as deleted.
+To flag a user as deleted use the [app_metadata](users/concepts/overview-user-metadata). In the following example, we will show you how to add a property called **deleted** to the **app_metadata** field. This allows you to configure the authentication process to treat all uses with this property set to true as deleted.
To update a user's metadata, use the [Update a user endpoint](/api/management/v2#!/Users/patch_users_by_id).
diff --git a/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-custom-ui.md b/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-custom-ui.md
index 49b844bf76..42ec9fb97e 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-custom-ui.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-custom-ui.md
@@ -2,20 +2,25 @@
title: "GDPR: Track consent with your custom UI"
description: This tutorial describes how you can use either auth0.js or the Auth0 APIs to capture consent information when you use your own custom UI for logins
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType: tutorial
+useCase: compliance
---
# Track Consent with Custom UI
-In this tutorial we will see how you can use auth0.js or the Auth0 APIs to ask for consent information and save the input at the user's [metadata](/metadata).
+In this tutorial we will see how you can use auth0.js or the Auth0 APIs to ask for consent information and save the input at the user's [metadata](/users/concepts/overview-user-metadata).
<%= include('../_legal-warning.md') %>
## Overview
-We will capture consent information, under various scenarios, and save this at the user's metadata.
+We will capture consent information, under various scenarios, and save this in the user's metadata.
-All scenarios will save the following properties at the [user's metadata](/metadata):
-- a `consentGiven` property, with true/false values, shows if the user has provided consent (true) or not (false)
-- a `consentTimestamp` property, holding the Unix timestamp of when the user provided consent
+All scenarios will save the following properties in the user's metadata:
+- `consentGiven` (true/false) shows if the user has provided consent (true) or not (false)
+- `consentTimestamp` (Unix timestamp) indicates when the user provided consent
For example:
@@ -28,14 +33,14 @@ For example:
We will see four different implementations for this:
-1. one that displays a flag, works for database connections, and uses the [auth0.js](/libraries/auth0js) library to create the user (used by Single Page Applications)
+1. one that displays a flag, works for database connections, and uses the [auth0.js](/libraries/auth0js) library to create the user (used by Single-Page Applications)
1. one that displays a flag, works for database connections, and uses the [Authentication API](/api/authentication#signup) to create the user (used by Regular Web Apps)
1. one that displays a flag, works for social connections, and uses the [Management API](/api/management/v2) to update the user's information (used either by SPAs or Regular Web Apps)
1. one that redirects to another page where the Terms & Conditions and/or privacy policy information can be reviewed and consent info can be provided (used either by SPAs or Regular Web Apps)
## Option 1: Use auth0.js
-In this section, we will use a simple Single Page Application and customize the login widget to add a flag which users can use to provide consent information. Instead of building an app from scratch, we will use [Auth0's JavaScript Quickstart sample](/quickstart/spa/vanillajs). We will also use [Auth0's Universal Login Page](/hosted-pages/login) so we can implement a [Universal Login experience](/guides/login/centralized-vs-embedded), instead of embedding the login in our app.
+In this section, we will use a simple Single-Page Application and customize the login widget to add a flag which users can use to provide consent information. Instead of building an app from scratch, we will use [Auth0's JavaScript Quickstart sample](/quickstart/spa/vanillajs). We will also use [Auth0's Universal Login Page](/universal-login) so we can implement a [Universal Login experience](/guides/login/centralized-vs-embedded), instead of embedding the login in our app.
This works **only** for database connections (we will use Auth0's infrastructure, instead of setting up our own database).
@@ -53,7 +58,7 @@ This works **only** for database connections (we will use Auth0's infrastructure
1. [Set the Client ID and Domain](https://github.com/auth0-samples/auth0-javascript-samples/tree/master/01-Login#set-the-client-id-and-domain) values.
-1. Go to [Dashboard > Hosted Pages](${manage_url}/#/login_page). At the **Login** tab enable the toggle.
+1. Go to [Dashboard > Universal Login](${manage_url}/#/login_settings). At the **Login** tab enable the toggle.
1. At the **Default Templates** dropdown make sure that `Custom Login Form` is picked. The code is prepopulated for you.
@@ -131,10 +136,10 @@ If you use social connections, then you cannot use the Authentication API to cre
What you have to do instead is let your user sign up with the social provider (which will create a user record at Auth0) and then use the [Management API](/api/management/v2) to update the user's information.
-Before you call the Management API you need to get a valid token. For details on how to do that see [The Auth0 Management APIv2 Token](/api/management/v2/tokens#1-get-a-token).
+Before you call the Management API you need to get a valid token. For details see [Get Access Tokens for Production](/api/management/v2/get-access-tokens-for-production).
:::panel Get a token from an SPA
-The linked article uses the [Client Credentials OAuth 2.0 grant](/api-auth/grant/client-credentials) to get a token, which you cannot use from an app running on the browser. What you can use instead is the [Implicit Grant](/api-auth/grant/implicit). Set the **audience** request parameter to `https://${account.namespace}/api/v2/` and the **scope** parameter to the scope `create:current_user_metadata`. You can use the Access Token you will get at the response to call the [Update User endpoint of the Management API](/api/management/v2#!/Users/patch_users_by_id).
+The linked article uses the [Client Credentials Flow](/flows/concepts/client-credentials) to get a token, which you cannot use from an app running on the browser. What you can use instead is the [Implicit Flow](/flows/concepts/implicit). Set the **audience** request parameter to `https://${account.namespace}/api/v2/` and the **scope** parameter to the scope `create:current_user_metadata`. You can use the Access Token you will get at the response to call the [Update User endpoint of the Management API](/api/management/v2#!/Users/patch_users_by_id).
:::
Once you have a valid token, use the following snippet to update the user's metadata.
@@ -164,21 +169,22 @@ Once you have a valid token, use the following snippet to update the user's meta
}
```
-Note that in order to make this call you need to know the unique `user_id`. You can retrieve this from the `sub` claim of the [ID Token](/tokens/id-token), if you got one from the response. Alternatively, if all you have is the email, you can retrieve the Id by calling another endpoint of the Management API. For more information see [Search Users by Email](/users/search/best-practices#users-by-email).
+Note that in order to make this call you need to know the unique `user_id`. You can retrieve this from the `sub` claim of the [ID Token](/tokens/concepts/id-tokens), if you got one from the response. Alternatively, if all you have is the email, you can retrieve the Id by calling another endpoint of the Management API. For more information see [Search Users by Email](/best-practices/search-best-practices#users-by-email).
## Option 4: Redirect to another page
-If you want to display more information to your user, then upon signup you can redirect to another page where you ask for consent and any additional info, and then redirect back to finish the authentication transaction. This can be done with [redirect rules](/rules/redirect). That same rule can be used to save the consent information at the user's metadata so we can track this information and not ask for consent upon next login.
+If you want to display more information to your user, then upon signup you can redirect to another page where you ask for consent and any additional info, and then redirect back to finish the authentication transaction. This can be done with [redirect rules](/rules/redirect). That same rule can be used to save the consent information at the user's metadata so you can track this information and not ask for consent upon next login.
<%= include('./_redirect.md') %>
-To test this configuration:
-1. Run the application and go to [http://localhost:3000](http://localhost:3000)
-1. Sign up with a new user. You will be navigated to the consent form.
-1. Check the **I agree** flag and click **Submit**
-1. Go to [Dashboard > Users](${manage_url}/#/users) and search for your new user
-1. Go to **User Details** and scroll down to the **Metadata** section.
-1. At the **user_metadata** text area you should see the `consentGiven` metadata set to `true`, and the `consentTimestamp` set to the Unix timestamp of the moment the user consented
+To test this configuration:
+
+1. Run the application and go to [http://localhost:3000](http://localhost:3000).
+2. Sign up with a new user. You will be redirected to the consent form.
+3. Check the **I agree** flag, and click **Submit**.
+4. Go to [Dashboard > Users](${manage_url}/#/users), and search for your new user.
+5. Go to **User Details**, and scroll down to the **Metadata** section.
+6. At the **user_metadata** text area, you should see the `consentGiven` metadata set to `true` and the `consentTimestamp` set to the Unix timestamp of the moment the user consented.

diff --git a/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-lock.md b/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-lock.md
index ed0ec72917..713dd25c9c 100644
--- a/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-lock.md
+++ b/articles/compliance/gdpr/features-aiding-compliance/user-consent/track-consent-with-lock.md
@@ -2,22 +2,27 @@
title: "GDPR: Track Consent with Lock"
description: This tutorial describes how you can customize Lock to capture consent information
toc: true
+topics:
+ - compliance
+ - gdpr
+contentType: tutorial
+useCase: compliance
---
# Track Consent with Lock
-In this tutorial we will see how you can use Lock to ask for consent information, and then save this input at the user's [metadata](/metadata).
+In this tutorial we will see how you can use Lock to ask for consent information, and then save this input at the user's [metadata](/users/concepts/overview-user-metadata).
<%= include('../_legal-warning.md') %>
## Overview
-We will configure a simple JavaScript Single Page Application and a database connection (we will use Auth0's infrastructure, instead of setting up our own database).
+We will configure a simple JavaScript Single-Page Application and a database connection (we will use Auth0's infrastructure, instead of setting up our own database).
-Instead of building an app from scratch, we will use [Auth0's JavaScript Quickstart sample](/quickstart/spa/vanillajs). We will also use [Auth0's Universal Login Page](/hosted-pages/login) so we can implement a [Universal Login experience](/guides/login/centralized-vs-embedded), instead of embedding the login in our app.
+Instead of building an app from scratch, we will use [Auth0's JavaScript Quickstart sample](/quickstart/spa/vanillajs). We will also use [Auth0's Universal Login Page](/universal-login) so we can implement a [Universal Login experience](/guides/login/centralized-vs-embedded), instead of embedding the login in our app.
We will capture consent information, under various scenarios, and save this at the user's metadata.
-All scenarios will save the following properties at the [user's metadata](/metadata):
+All scenarios will save the following properties at the [user's metadata](/users/concepts/overview-user-metadata):
- a `consentGiven` property, with true/false values, shows if the user has provided consent (true) or not (false)
- a `consentTimestamp` property, holding the Unix timestamp of when the user provided consent
@@ -47,7 +52,7 @@ We will see three different implementations for this:
1. Copy the **Client Id** and **Domain** values. You will need them in a while.
-1. Go to [Dashboard > Connections > Database](${manage_url}/#/connections/database) and create a new connection. Click **Create DB Connection**, set a name for the new connection, and click **Save**. You can also [enable a social connection](/identityproviders#social) at [Dashboard > Connections > Social](${manage_url}/#/connections/social) (we will [enable Google login](/connections/social/google) for the purposes of this tutorial).
+1. Go to [Dashboard > Connections > Database](${manage_url}/#/connections/database) and create a new connection. Click **Create DB Connection**, set a name for the new connection, and click **Save**. You can also [enable a social connection](/connections/identity-providers-social) at [Dashboard > Connections > Social](${manage_url}/#/connections/social) (we will [enable Google login](/connections/social/google) for the purposes of this tutorial).
1. Go to the connection's **Applications** tab and make sure your newly created application is enabled.
@@ -74,7 +79,7 @@ This works both for database connections and social logins.
//code reducted for simplicity
},
languageDictionary: {
- signUpTerms: "I agree to the terms of service and privacy policy."
+ signUpTerms: "I agree to the terms of service and privacy policy."
},
mustAcceptTerms: true,
//code reducted for simplicity
@@ -148,6 +153,8 @@ If you are using social logins, adding custom fields is not an option, but you c
<%= include('./_redirect.md') %>
+<%= include('../../../../_includes/_parental-consent') %>
+
We are done with the configuration part, let's test!
## Test the configuration
diff --git a/articles/compliance/gdpr/features-aiding-compliance/user-consent/webtask-redirect.md b/articles/compliance/gdpr/features-aiding-compliance/user-consent/webtask-redirect.md
new file mode 100644
index 0000000000..456054d2ce
--- /dev/null
+++ b/articles/compliance/gdpr/features-aiding-compliance/user-consent/webtask-redirect.md
@@ -0,0 +1,68 @@
+---
+section: compliance
+description: Learn how to host a redirect form using Webtask and redirect users to the form.
+contentType: how-to
+sitemap: false
+public: false
+---
+# Redirect Users to Consent Form Hosted Using Webtask
+
+:::warning
+Webtask is no longer accepting new signups. We recommend hosting your consent form on another hosting service like Heroku.
+:::
+
+For simplicity, we will use this [sample consent form](https://wt-peter-auth0_com-0.run.webtask.io/simple-redirect-rule-consent-form). This is a form we have hosted for you, but later on we will see how to host your own version of this form (with your own URL). You can find the code at [Auth0 Redirect Rules repo](https://github.com/auth0/rules/blob/master/redirect-rules/simple/webtask.js).
+
+:::note
+If you are implementing this from a regular web app, hosting your own form, then you can also save the consent information at the `user_metadata` using the [Management API's Update User endpoint](/api/management/v2#!/Users/patch_users_by_id).
+:::
+
+1. First, we will add the rule. Go to [Dashboard > Rules](${manage_url}/#/rules) and click **Create Rule**. At the **Rules Templates** select **empty rule**. Change the default rule's name (`empty rule`) to something descriptive, for example `Redirect to consent form`.
+
+2. Add the following JavaScript code and save your changes. The code redirects the user to the `CONSENT_FORM_URL` URL (we will configure this at the next step). Once the user hits **Submit** at the consent form, the rule runs again as part of the callback. At this point we persist the information at the `user_metadata`.
+
+ ```js
+ function redirectToConsentForm (user, context, callback) {
+ var consentGiven = user.user_metadata && user.user_metadata.consentGiven;
+ // redirect to consent form if user has not yet consented
+ if (!consentGiven && context.protocol !== 'redirect-callback') {
+ var auth0Domain = auth0.baseUrl.match(/([^:]*:\/\/)?([^\/]+\.[^\/]+)/)[2];
+ context.redirect = {
+ url: configuration.CONSENT_FORM_URL +
+ (configuration.CONSENT_FORM_URL.indexOf('?') === -1 ? '?' : '&') +
+ 'auth0_domain=' + encodeURIComponent(auth0Domain)
+ };
+ }
+ // if user clicked 'I agree' on the consent form, persist it to their profile
+ // so they don't get prompted again
+ if (context.protocol === 'redirect-callback') {
+ if (context.request.body.confirm === 'yes') {
+ user.user_metadata = user.user_metadata || {};
+ user.user_metadata.consentGiven = true;
+ user.user_metadata.consentTimestamp = Date.now();
+ auth0.users.updateUserMetadata(user.user_id, user.user_metadata)
+ .then(function(){
+ callback(null, user, context);
+ })
+ .catch(function(err){
+ callback(err);
+ });
+ } else {
+ callback(new UnauthorizedError('User did not consent!'));
+ }
+ }
+ callback(null, user, context);
+ }
+ ```
+
+3. Go back to [Dashboard > Rules](${manage_url}/#/rules), scroll down, and under **Settings**, create a Key/Value pair as follows:
+ - **Key**: `CONSENT_FORM_URL`
+ - **Value**: `https://wt-peter-auth0_com-0.run.webtask.io/simple-redirect-rule-consent-form`
+
+If you want to work with your own implementation of the consent form webtask, you can host your own version of the webtask.js script. For instructions see [Consent Form Setup](https://github.com/auth0/rules/tree/master/redirect-rules/simple#consent-form-setup).
+
+To learn more about redirect rules, see [Redirect Users from Rules](/rules/redirect).
+
+:::warning
+If you plan on using this approach in a production environment, make sure to review [Trusted Callback URL's](https://github.com/auth0/rules/tree/master/redirect-rules/simple#trusted-callback-urls) and [Data Integrity](https://github.com/auth0/rules/tree/master/redirect-rules/simple#data-integrity) (both sections address some security concerns).
+:::
diff --git a/articles/compliance/gdpr/gdpr-summary.md b/articles/compliance/gdpr/gdpr-summary.md
index 0e42ddf976..5c03ed14e2 100644
--- a/articles/compliance/gdpr/gdpr-summary.md
+++ b/articles/compliance/gdpr/gdpr-summary.md
@@ -1,6 +1,11 @@
---
title: General Data Protection Regulation (GDPR) - A Summary
description: A summary of how GDPR affects Auth0, its customers, and the end users
+topics:
+ - compliance
+ - gdpr
+contentType: concept
+useCase: compliance
---
# General Data Protection Regulation (GDPR) - A Summary
diff --git a/articles/compliance/gdpr/index.md b/articles/compliance/gdpr/index.md
index 01a8e9dd8b..6ebbe9aa63 100644
--- a/articles/compliance/gdpr/index.md
+++ b/articles/compliance/gdpr/index.md
@@ -2,6 +2,13 @@
title: Auth0 and General Data Protection Regulation
description: How Auth0 complies with the EU's General Data Protection Regulation (GDPR)
classes: topic-page
+topics:
+ - compliance
+ - gdpr
+contentType:
+ - index
+ - concept
+useCase: compliance
---
diff --git a/articles/compliance/gdpr/roles-responsibilities.md b/articles/compliance/gdpr/roles-responsibilities.md
index 91a5c29a9e..2616a06e12 100644
--- a/articles/compliance/gdpr/roles-responsibilities.md
+++ b/articles/compliance/gdpr/roles-responsibilities.md
@@ -1,6 +1,11 @@
---
title: Roles and Responsibilities under GDPR
description: The roles and responsibilities of data controllers and processors under GDPR
+topics:
+ - compliance
+ - gdpr
+contentType: reference
+useCase: compliance
---
# Roles and Responsibilities under GDPR
diff --git a/articles/compliance/gdpr/security-advice-for-customers.md b/articles/compliance/gdpr/security-advice-for-customers.md
index a71c6cbea3..686de1a708 100644
--- a/articles/compliance/gdpr/security-advice-for-customers.md
+++ b/articles/compliance/gdpr/security-advice-for-customers.md
@@ -1,13 +1,18 @@
---
title: Security Advice for Customers
description: How to protect your end users' data
+topics:
+ - compliance
+ - gdpr
+contentType: reference
+useCase: compliance
---
# Security Advice for Customers
Auth0 recommends the following practices to help ensure the security of your end users data and minimize the probability of a data breach:
* Protect client secrets and keys
-* Protect Management Dashboard credentials, and require multifactor authentication for access to the Dashboard
+* Protect Management Dashboard credentials, and require multi-factor authentication for access to the Dashboard
* Review the list of administrators for the Dashboard on a regular basis and remove outdated entries
* Review the list of connections and applications associated with your Auth0 tenants and remove outdated entries
* Ensure that Dashboard administrators use corporate credentials that can be easily revoked if necessary, *not* personal credentials such as a personal email account
diff --git a/articles/compliance/index.md b/articles/compliance/index.md
index 2c3be734f1..fc73492640 100644
--- a/articles/compliance/index.md
+++ b/articles/compliance/index.md
@@ -2,6 +2,13 @@
title: Compliance
description: Information about Auth0 Compliance and Certifications
classes: topic-page
+topics:
+ - compliance
+ - gdpr
+contentType:
+ - index
+ - reference
+useCase: compliance
---
@@ -9,12 +16,15 @@ classes: topic-page
Auth0 maintains and meets the requirements for multiple compliance frameworks and certifications.
Auth0 is working toward GDPR readiness. Auth0 provides information to its customers to help them understand how features and functionality of the Auth0 platform may affect their GDPR compliance obligations.
+
Auth0 is GDPR ready. Auth0 provides information to its customers to help them understand how features and functionality of the Auth0 platform may affect their GDPR compliance obligations.
Auth0 is certified under the Privacy Shield Program, specifically the EU-US Privacy Shield Framework and the Swiss-US Privacy Shield Framework. You can find further details on our Privacy page.
Auth0 is considered a Business Associate as defined by the US HIPAA and HITECH legislation.
For Auth0 customers who qualify as a Covered Entity under US HIPAA legislation and related legislation and regulations and who provide ePHI (electronic Protected Health Information) to Auth0 as part of the Auth0 user profile, Auth0 may qualify as a business associate. Auth0 can provide its Business Associate Agreement to such customers upon request.
Auth0 undergoes a SOC 2 Type II audit by an independent auditor annually. This audit covers our product, infrastructure, and policies. The SOC 2 Type II Audit Report is available to enterprise level customers upon request with a non-disclosure agreement (NDA) signed by a corporate officer authorized to represent the company.
+ SOC 2
+
Auth0 undergoes a SOC 2 Type II audit by an independent auditor annually. This audit covers our product, infrastructure, and policies. The SOC 2 Type II Audit Report is available to enterprise level customers upon request with a non-disclosure agreement (NDA) signed by a corporate officer authorized to represent the company. To request the report, please contact your assigned Technical Account Manager.
Auth0 undergoes an ISO 27001/27018 audit by an independent auditor annually. Our ISO 27001/27018 certificate is available in our Support Center. We can also share our Statement of Applicability (SOA) upon request with a non-disclosure agreement (NDA) signed by a corporate officer authorized to represent the company. To request the SOA, please contact your assigned Technical Account Manager.
+
+
+ PCI DSS
+
PCI certification is available as an add-on for Auth0's Private Cloud deployment model. Auth0 undergoes a PCI audit by an independent auditor annually. Our Attestation of Compliance (AOC) is available upon request. To request the AOC, please contact your assigned Technical Account Manager.
diff --git a/articles/configure/index.md b/articles/configure/index.md
new file mode 100644
index 0000000000..c0b668e328
--- /dev/null
+++ b/articles/configure/index.md
@@ -0,0 +1,21 @@
+---
+classes: topic-page
+title: Configuration
+description: Learn how to configure tenants, applications, APIs, and other settings in Auth0
+topics:
+ - configuration
+contentType: index
+---
+# Configuration
+
+Learn how to configure tenants, applications, APIs, and other settings in Auth0.
+
+<%= include('../_includes/_topic-links', { links: [
+ 'dashboard/reference/settings-tenant',
+ 'dashboard/reference/settings-application',
+ 'dashboard/reference/settings-api',
+ 'sso/current',
+ 'anomaly-detection',
+ 'protocols/saml',
+ 'guides/ip-whitelist',
+] }) %>
diff --git a/articles/connections/_call-api.md b/articles/connections/_call-api.md
index e13d64f14c..c508d4c916 100644
--- a/articles/connections/_call-api.md
+++ b/articles/connections/_call-api.md
@@ -1,11 +1,7 @@
-Once you successfully authenticate a user, ${idp} includes an [Access Token](/tokens/access-token) in the user profile it returns to Auth0.
+Once a user successfully authenticates, ${idp} will include an Access Token in the user profile it returns to Auth0. You can use this token to call ${idp}'s API.
-You can then use this token to call their API.
+To get the ${idp} Access Token, you must retrieve the full user's profile using the Auth0 Management API and extract the Access Token from the response. For detailed steps, see [Call an Identity Provider's API](/connections/calling-an-external-idp-api).
-In order to get a ${idp} Access Token, you have to retrieve the full user's profile, using the Auth0 Management API, and extract the Access Token from the response. For detailed steps refer to [Call an Identity Provider API](/connections/calling-an-external-idp-api).
+Using the token, you can call ${idp}'s API following ${idp}'s documentation.
-Once you have the token you can call the API, following ${idp}'s documentation.
-
-::: note
-For more information on these tokens, refer to [Identity Provider Access Tokens](/tokens/idp).
-:::
\ No newline at end of file
+Optional: Get a [Refresh Token](/tokens/guides/get-refresh-tokens) from ${idp} to refresh your Access Token once it expires. To ensure your application is secure, pay close attention to the [restrictions on using Refresh Tokens](/tokens/concepts/refresh-tokens#restrictions-and-limitations).
diff --git a/articles/connections/_find-auth0-domain-redirects.md b/articles/connections/_find-auth0-domain-redirects.md
new file mode 100644
index 0000000000..0c1fad7485
--- /dev/null
+++ b/articles/connections/_find-auth0-domain-redirects.md
@@ -0,0 +1,5 @@
+::: panel Find your Auth0 domain name for redirects
+If your Auth0 domain name is not shown above and you are not using our custom domains feature, your domain name is your tenant name, your regional subdomain (unless your tenant is in the US region and was created before June 2020), plus`.auth0.com`. For example, if your tenant name were `exampleco-enterprises`, your Auth0 domain name would be `exampleco-enterprises.us.auth0.com` and your redirect URI would be `https://exampleco-enterprises.us.auth0.com/login/callback`. (If your tenant is in the US and was created before June 2020, then your domain name would be `https://exampleco-enterprises.auth0.com`.)
+
+If you are using [custom domains](https://auth0.com/docs/custom-domains), your redirect URI will have the following format: `https:///login/callback`.
+:::
\ No newline at end of file
diff --git a/articles/connections/_includes/_options-prop-pw-complexity.md b/articles/connections/_includes/_options-prop-pw-complexity.md
new file mode 100644
index 0000000000..c3d3a262aa
--- /dev/null
+++ b/articles/connections/_includes/_options-prop-pw-complexity.md
@@ -0,0 +1,5 @@
+Allows you to set password complexity options for this connection.
+
+Properties include:
+
+- `min_length` (integer): The minimum character length of a password. NIST recommends a minimum character length of 8, and suggests that length is a better indicator of strength than complexity. Maximum: 128.
\ No newline at end of file
diff --git a/articles/connections/_includes/_options-prop-pw-dictionary.md b/articles/connections/_includes/_options-prop-pw-dictionary.md
new file mode 100644
index 0000000000..091dfd1894
--- /dev/null
+++ b/articles/connections/_includes/_options-prop-pw-dictionary.md
@@ -0,0 +1,6 @@
+When enabled, the system will disallow passwords that are part of the password dictionary, which includes a list of the [10,000 most common passwords](https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10k-most-common.txt). You may also customize the dictionary with your own entries.
+
+Properties include:
+
+- `enable` (boolean): Whether or not to enable password dictionary.
+- `dictionary` (array (string)): Custom entries that you would like to add to the password dictionary for this connection. Each entry may contain a maximum of 50 characters. We use case-insensitive comparison. Maximum: 200.
\ No newline at end of file
diff --git a/articles/connections/_includes/_options-prop-pw-expiration.md b/articles/connections/_includes/_options-prop-pw-expiration.md
new file mode 100644
index 0000000000..99d8a0942a
--- /dev/null
+++ b/articles/connections/_includes/_options-prop-pw-expiration.md
@@ -0,0 +1,7 @@
+When enabled, the system will enforce password expiration for this connection.
+
+Properties include:
+
+- `enable` (boolean): Whether or not to enable password expiration.
+- `warn_after` (integer): The timeframe (in days) after which the user will be warned that their password will expire. Maximum: 365. Default: 90.
+- `expire_after` (integer): The timeframe (in days) after which a password will expire. Maximum: 365. Default: 90.
\ No newline at end of file
diff --git a/articles/connections/_includes/_options-prop-pw-history.md b/articles/connections/_includes/_options-prop-pw-history.md
new file mode 100644
index 0000000000..d3c16a7903
--- /dev/null
+++ b/articles/connections/_includes/_options-prop-pw-history.md
@@ -0,0 +1,6 @@
+When enabled, the system will maintain a password history for each user and prevent the reuse of passwords included in the history. Any existing users in the connection will be unaffected; the system will maintain their password history going forward.
+
+Properties include:
+
+- `enable` (boolean): Whether or not to enable password history tracking.
+- `size` (integer): The number of passwords to track. Maximum: 24.
\ No newline at end of file
diff --git a/articles/connections/_includes/_options-prop-pw-no-pers-info.md b/articles/connections/_includes/_options-prop-pw-no-pers-info.md
new file mode 100644
index 0000000000..3d513078be
--- /dev/null
+++ b/articles/connections/_includes/_options-prop-pw-no-pers-info.md
@@ -0,0 +1,5 @@
+When enabled, the system will disallow passwords that contain any part of the user's personal data, including the user's `name`, `username`, `nickname`, `email`, local-part of `email`, `user_metadata.name`, `user_metadata.first`, and `user_metadata.last`.
+
+Properties include:
+
+- `enable` (boolean): Whether or not to enable no personal information in passwords.
\ No newline at end of file
diff --git a/articles/connections/_includes/_options-upstream-params.md b/articles/connections/_includes/_options-upstream-params.md
new file mode 100644
index 0000000000..c68e347dd1
--- /dev/null
+++ b/articles/connections/_includes/_options-upstream-params.md
@@ -0,0 +1,9 @@
+Allows you to pass static provider-specific parameters to an [Identity Provider](/connections) for this connection. Not all Identity Providers support upstream parameters, so you will need to check with the Identity Provider before using this element.
+
+Properties include:
+
+- Parameter (object): The name of the parameter accepted by the Identity Provider. Will contain one of the following two properties, depening on how you are using the upstream parameters.
+ - `alias` (string): The existing accepted OAuth 2.0/OIDC parameter, which maps to the parameter accepted by the Identity Provider. Used when passing dynamic upstream parameters per user. Allowed values include: `acr_values`, `audience`, `client_id`, `display`, `id_token_hint`, `login_hint`, `max_age`, `prompt`, `resource`, `response_mode`, `response_type`, and `ui_locales`.
+ - `value` (string): The value of the parameter. Used when passing static upstream parameters per connection.
+
+For more information and examples of how to use upstream parameters, see [Pass Parameters to Identity Providers](/connections/pass-parameters-to-idps).
\ No newline at end of file
diff --git a/articles/connections/_includes/_options-validation.md b/articles/connections/_includes/_options-validation.md
new file mode 100644
index 0000000000..34479ba78b
--- /dev/null
+++ b/articles/connections/_includes/_options-validation.md
@@ -0,0 +1,7 @@
+Allows you to set validation options for this connection.
+
+Properties include:
+
+- `username` (object):
+ - `min` (integer): The minimum length of a user's username.
+ - `max` (integer): The maximum length of a user's username.
diff --git a/articles/connections/_otp-limitations.md b/articles/connections/_otp-limitations.md
new file mode 100644
index 0000000000..a7febd28a7
--- /dev/null
+++ b/articles/connections/_otp-limitations.md
@@ -0,0 +1,4 @@
+* Only the last one-time password (or link) issued will be accepted. Once the latest one is issued, any others are invalidated. Once used, the latest one is also invalidated.
+* Only three failed attempts to input the one-time password are allowed. After this, a new code will need to be requested.
+* The one-time password issued will be valid (by default) for three minutes before it expires.
+* If you choose to extend the amount of time it takes for your one-time password to expire, you should also extend the length of the one-time password code. Otherwise, an attacker has a larger window of time to attempt to guess a short code.
diff --git a/articles/connections/_quickstart-links.md b/articles/connections/_quickstart-links.md
index 9e3955fb20..a85112173d 100644
--- a/articles/connections/_quickstart-links.md
+++ b/articles/connections/_quickstart-links.md
@@ -1,11 +1,9 @@
## Next Steps
-Now that you have a working connection, the next step is to configure your application to use it. You can follow our step-by-step quickstarts or use directly our libraries and API.
-
::: next-steps
-* [Get started with our Quickstarts](/quickstarts)
-* [Configure your application using our libraries](/libraries)
-* [Call our Authentication API](/api/authentication)
-* [Read more about client authentication](/application-auth)
+* [Integrate with Auth0 using one of our libraries](/libraries)
+* [Integrate with Auth0 using our Authentication API](/api/authentication)
+* [Read more about the authentication flow](/application-auth)
+* [Pass additional parameters to the Identity Provider](/connections/pass-parameters-to-idps)
* [Re-prompt users for permissions](/connections/social/reprompt-permissions)
:::
diff --git a/articles/connections/adding-generic-oauth1-connection.md b/articles/connections/adding-generic-oauth1-connection.md
index 45aef0fb2c..777e5f5471 100644
--- a/articles/connections/adding-generic-oauth1-connection.md
+++ b/articles/connections/adding-generic-oauth1-connection.md
@@ -1,6 +1,13 @@
---
title: Adding a generic OAuth1 Authorization Server to Auth0
description: How to add a generic Oauth1 Authorization Server to Auth0.
+topics:
+ - connections
+ - oauth1
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Adding a generic OAuth1 Authorization Server to Auth0
@@ -18,7 +25,7 @@ curl -X POST
```
:::note
-Replace `YOUR_MANAGEMENT_API_TOKEN` with a valid token. For info on how to get one, see [The Auth0 Management APIv2 Token](/api/management/v2/tokens).
+Replace `YOUR_MANAGEMENT_API_TOKEN` with a valid token. For info on how to get one, see [Access Tokens for the Management API](/api/management/v2/tokens).
:::
```json
@@ -70,7 +77,7 @@ function(token, tokenSecret, ctx, callback){
The `token` and `tokenSecret` parameters will often be used for authenticating requests to the provider's API.
::: note
-We recommend using the field names in the [normalized profile](/user-profile).
+We recommend using the field names in the [normalized profile](/users/normalized).
:::
Notice that you can manipulate the profile returned from the provider to filter/remove/add anything in it. However, we recommend you keep this script as simple as possible. More sophisticated manipulation of the user information can be achieved through [Rules](/rules).
@@ -81,7 +88,7 @@ One advantage of using Rules is that they apply to __any__ connection.
## Using your new connection
-You can use any of the Auth0 standard mechanisms to login a user with the new connection (such as direct links, [Auth0 Lock](lock), [auth0.js](auth0js), and so on).
+You can use any of the Auth0 standard mechanisms to login a user with the new connection (such as direct links, Auth0 Lock, [auth0.js](auth0js), and so on).
A direct link would look like:
diff --git a/articles/connections/adding-scopes-for-an-external-idp.md b/articles/connections/adding-scopes-for-an-external-idp.md
index 8488d7a64a..2cb42398dc 100644
--- a/articles/connections/adding-scopes-for-an-external-idp.md
+++ b/articles/connections/adding-scopes-for-an-external-idp.md
@@ -1,7 +1,14 @@
---
description: How to add scopes to your IdP connection.
+topics:
+ - connections
+ - scopes
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Add scopes/permissions to call Identity Provider's APIs
+# Add scopes/permissions to call Identity Provider's APIs
Once user is logged in, you can get the user profile and then the associated `accessToken` to call the Identity Provider APIs as described in: [Call an Identity Provider API](/what-to-do-once-the-user-is-logged-in/calling-an-external-idp-api)
@@ -11,15 +18,15 @@ There are two ways you can use to request the correct permissions.
## 1. Change Identity Provider Settings
-To configure the scopes/permissions needed from the user, go to the [Connections > Social](${manage_url}/#/connections/social) section of Auth0 Dashboard. There, you can click on an IdP to select the particular scopes required.
+To configure the scopes/permissions needed from the user, go to [Auth0 Dashboard > Authentication > Social](${manage_url}/#/connections/social), and select an IdP. You can select the required permissions listed on the configuration screen.
-For example, if you click the Google connection, you can select the required scopes listed in the configuration pop-up:
+For example, if you click the **Google / Gmail** connection, you can configure Google-specific permissions:
-
+
## 2. Pass Scopes to Authorize endpoint
-You can also pass the scopes you wish to request as a comma-separated list in the `connection_scope` parameter when calling the [authorize endpoint](/api/authentication#login). For example, if you want to request the `https://www.googleapis.com/auth/contacts.readonly` and `https://www.googleapis.com/auth/analytics` scopes from Google, you can pass these along with the `connection` parameter to ensure the user logs in with their Google account:
+You can also pass the scopes/permissions you wish to request as a comma-separated list in the `connection_scope` parameter when calling the [authorize endpoint](/api/authentication#login). For example, if you want to request the `https://www.googleapis.com/auth/contacts.readonly` and `https://www.googleapis.com/auth/analytics` scopes from Google, you can pass these along with the `connection` parameter to ensure the user logs in with their Google account:
```text
https://${account.namespace}/authorize
@@ -33,5 +40,5 @@ https://${account.namespace}/authorize
```
::: note
-Please note that in the example request above, the value of the `connection_scope` parameter is URL Encoded. The decoded value which is passed to Google is `https://www.googleapis.com/auth/analytics, https://www.googleapis.com/auth/contacts.readonly`
+Please note that in the example request above, the value of the `connection_scope` parameter is URL encoded. The decoded value that is passed to Google is `https://www.googleapis.com/auth/analytics, https://www.googleapis.com/auth/contacts.readonly`
:::
diff --git a/articles/connections/apple-siwa/set-up-apple.md b/articles/connections/apple-siwa/set-up-apple.md
new file mode 100644
index 0000000000..6a02e428f6
--- /dev/null
+++ b/articles/connections/apple-siwa/set-up-apple.md
@@ -0,0 +1,81 @@
+---
+title: Register Apps in the Apple Developer Portal
+description: Learn how to set up your application with Apple before you set up your Apple connection in the Auth0 Dashboard.
+topics:
+ - authentication
+ - connections
+ - social
+ - apple
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
+---
+# Register Apps in the Apple Developer Portal
+
+Before you configure an Apple social connection in the Auth0 Dashboard, you need to set up your application on your Apple Developer account in the Apple Developer Portal. Once that is complete, you can use the assigned credentials you receive from Apple to set up your Apple connection in the Auth0 Dashboard.
+
+::: note
+You can test the Apple connection with Auth0's developer credentials first by navigating to [Auth0 Dashboard > Authentication > Social](${manage_url}/#/connections/social). Locate the **Apple** connection, and select the More Options menu (**...***), then select **Try Connection**.
+
+Prior to using the connection in production, you must provide your own credentials as shown below.
+:::
+
+After you register your application, you will be given the following IDs and keys to use in the application connection settings in the Dashboard:
+
+* Services ID (Client ID)
+* Apple Team ID
+* Client Secret Signing Key
+* Key ID
+
+## Prerequisites
+
+Before you can register your app in the Apple Developer Portal, you must have an [Apple Developer](https://developer.apple.com/programs/) account, which is a paid account with Apple. (There is no free trial available unless you are part of their [iOS Developer University Program](https://developer.apple.com/support/compare-memberships/).)
+
+## Obtain Team ID
+
+1. Sign in to your [Apple Developer Account](https://developer.apple.com/account/#/overview/), and go to the [Membership page](https://developer.apple.com/account/#/membership/):
+ 
+2. Make note of your Team ID.
+
+## Create App ID
+
+1. On the Apple Developer Portal, go to **Certificates, IDs, & Profiles > Identifiers** and click the **blue plus icon** next to **Identifiers** to create a new App ID.
+2. Choose **App IDs** as the identifier type and click **Continue**.
+3. Provide a description and a Bundle ID (reverse-domain name style, e.g., `com.example`).
+4. Scroll down and check **Sign In with Apple**.
+5. Click **Continue**, and then click **Register**.
+
+## Create Services ID
+
+1. Return to the **Certificates, IDs, & Profiles** section, and select the **blue plus icon** next to **Identifiers**.
+ 
+2. Choose **Services IDs**, and select **Continue**. Fill in the description and identifier (`com.example.webapp`).
+3. After checking **Sign In with Apple**, select **Configure**, and define your **Web Domain** (`example.com`) and your **Return URL**. Make sure that your Return URL is your Auth0 domain, such as `foo.auth0.com` (or your Auth0 custom domain if you have one) and follows this format: `https://YOUR_AUTH0_DOMAIN/login/callback`.
+ 
+4. Click **Save**, **Continue**, and then click **Register**.
+
+::: note
+At this time, Apple does not require validation of the redirect URL, and doing so is typically not necessary.
+:::
+
+### Set up your Client Secret Signing Key
+
+1. Go to **Keys** under the **Certificates, Identifiers, & Profiles** section of your Apple developer dashboard.
+2. Select the **blue plus icon** to add a new key.
+3. Enter a **Key Name** and check the **Sign In with Apple** option.
+4. Select **Configure** to make sure the **Choose a Primary App ID** field is filled with the correct App ID.
+5. Select **Save**, **Continue**, and then **Register**.
+6. On the page to which you're redirected after registering, make note of the Key ID. Then download the key; it will have a .p8 extension.
+
+Next, you will use these credentials on the [Auth0 Dashboard > Authentication > Social](${manage_url}/#/connections/social) page to continue to configure your application. Depending on which type of application you want to configure, choose one of the following methods:
+
+* [Add Sign In with Apple to Native iOS Apps](/connections/apple-siwa/add-siwa-to-native-app)
+* [Add Sign In with Apple to Web or Other Apps](/connections/apple-siwa/add-siwa-to-web-app)
+
+## Keep reading
+
+* [iOS Swift - Sign In with Apple Quickstart](/quickstart/native/ios-swift-siwa)
+* [Rate Limits on Native Social Logins](/policies/rate-limits#limits-on-native-social-logins)
+* [Test Sign In with Apple Configuration](/connections/apple-siwa/test-siwa-connection)
diff --git a/articles/connections/apple-siwa/test-siwa-connection.md b/articles/connections/apple-siwa/test-siwa-connection.md
new file mode 100644
index 0000000000..61a1a36418
--- /dev/null
+++ b/articles/connections/apple-siwa/test-siwa-connection.md
@@ -0,0 +1,43 @@
+---
+title: Test Sign In with Apple Configuration
+description: Learn how to test the Auth0 Sign In with Apple app configuration.
+topics:
+ - authentication
+ - connections
+ - social
+ - apple
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
+---
+
+# Test Sign In with Apple Configuration
+
+::: note
+If you are using the Classic Universal Login flow, or embedding `Lock.js` in your application, make sure you are using `Lock.js` version 11.16 or later.
+:::
+
+1. Go to your application login page, and you should see an option for Sign In with Apple:
+
+ 
+
+2. Select **Continue with Apple**, then enter your Apple ID and password.
+
+3. You will be asked to verify a new device. Select **Allow**.
+
+4. Next, you'll be given a verification code. Make a note of this code, select **Done**, and then enter the code on the **Two-Factor Authentication** screen.
+
+ 
+
+5. When this is done, you'll have the option to edit your name and choose whether you'd like to share or hide your email. Make your choice, then select **Continue**.
+
+ 
+
+ You are now signed in to your application with Apple!
+
+## Keep reading
+
+* [iOS Swift - Sign In with Apple Quickstart](/quickstart/native/ios-swift-siwa)
+* [Rate Limits for Sign In with Apple](/policies/rate-limits#limits-on-sign-in-with-apple)
diff --git a/articles/connections/apple-siwa/troubleshooting.md b/articles/connections/apple-siwa/troubleshooting.md
new file mode 100644
index 0000000000..ad7234c93b
--- /dev/null
+++ b/articles/connections/apple-siwa/troubleshooting.md
@@ -0,0 +1,57 @@
+---
+title: Troubleshoot Sign in With Apple
+description: Describes troubleshooting steps for web and native apps using the Apple connection.
+topics:
+ - troubleshooting
+ - errors
+ - authentication
+ - connections
+ - social
+ - apple
+contentType:
+ - reference
+useCase:
+ - troubleshooting
+---
+
+# Troubleshoot Sign in with Apple
+
+## Configuration elements
+
+Ensure that the correct configuration elements are in place, both in the Auth0 Management Dashboard and in the Apple Developer Settings Console. Common configuration problems include:
+
+- **Using the wrong identifier**: Remember that Apple App IDs (also known as App Bundle Identifiers) need to be [configured in Auth0's advanced application settings](/connections/apple-siwa/add-siwa-to-native-app). Service IDs, which are used to configure web apps, need to be [configured in connection settings](/connections/apple-siwa/add-siwa-to-native-app). Switching these identifiers will result in failures.
+- **Missing return URLS for Web Apps**: When using Sign In with Apple for web apps, the Auth0 callback endpoint must be added to the list of Return URLs in the Apple Developer Settings Console. When not using custom domains, this will take the format: `https://TENANT.auth0.com/login/callback`.
+
+::: warning
+Remember that it's not possible to test native apps from the Auth0 Management Dashboard. The **Try Connection** button in the Apple connection only tests the web app flow. This is due to the fact that real devices are required for interaction with the Apple IdP using an App ID.
+:::
+
+## Tenant logs
+
+If your application successfully initiated the login flow with Auth0, the results will be reflected in the tenant logs. Native social exchanges will use the `sens` and `fens` event types to indicate success and failure (respectively), while web flows will use the standard `s` and `f` event types. All tenant logs interacting with the Apple IdP will use the connection value of `apple`.
+
+## Types of errors
+
+The following errors may be returned from the Apple IdP. Auth0 will relay both status codes and error messages from Apple should a request fail.
+
+| Error | Status Code | Description |
+| - | - | - |
+| `invalid_request` | 400 | The request parameters were incomplete or incorrect |
+| `invalid_grant` | 400 | The authorization code or refresh token presented to the Apple IdP is not valid |
+| `invalid_client` | 400 | Apple was unable to successfully authenticate the client with the provided credentials |
+| `server_error` | 500 | Other server-side issue inhibiting its ability to issue tokens |
+
+## Apple nuances
+Many identity providers have their own unique idiosyncrasies, and Apple is no exception. When integrating, be mindful of a few of its particular choices in implementation.
+
+- **Users are Unique Per Apple Development Account**: User identifiers in the Apple world are guaranteed to be both unique and persistent _per Apple Development Account_. If Apple user identifiers are sourced from more than one development account, know that the same user will be represented by different identifiers.
+- **Users can Choose Which Email to Share**: When users have multiple email addresses, they may choose which one is shared. Additionally, in the case of re-authentication, users may not pick the same email address. This means that the User ID should be used exclusively as the identifier, and account linking operations should use care.
+
+## Keep reading
+* [Register Apps in the Apple Developer Portal](/connections/apple-siwa/set-up-apple)
+* [Add Sign In with Apple to Native iOS Apps](/connections/apple-siwa/add-siwa-to-native-app)
+* [Add Sign In with Apple to Web or Other Apps](/connections/apple-siwa/add-siwa-to-web-app)
+* [Test Sign In with Apple Configuration](/connections/apple-siwa/test-siwa-connection)
+* [iOS Swift - Sign In with Apple Quickstart](/quickstart/native/ios-swift-siwa)
+* [Rate Limits on Native Social Logins](/policies/rate-limits#limits-on-native-social-logins)
diff --git a/articles/connections/calling-an-external-idp-api.md b/articles/connections/calling-an-external-idp-api.md
index 79037b6bde..1aca661cec 100644
--- a/articles/connections/calling-an-external-idp-api.md
+++ b/articles/connections/calling-an-external-idp-api.md
@@ -1,12 +1,21 @@
---
title: Call an Identity Provider API
-description: How to call an Identity Provider API
+description: Learn how to call an external Identity Provider API.
toc: true
crews: crew-2
+topics:
+ - connections
+ - social
+ - access-tokens
+ - api
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Call an Identity Provider API
-Once you successfully authenticate a user with an external Identity Provider (IdP), such as Facebook or GitHub, the IdP often includes an Access Token in the user profile it returns to Auth0.
+Once you successfully authenticate a user with an external Identity Provider (IdP), such as Facebook or GitHub, the IdP often includes an Access Token in the user profile it returns to Auth0.
You can retrieve and use this token to call the IdP's API.
@@ -14,72 +23,89 @@ You can retrieve and use this token to call the IdP's API.
This article assumes that you have already configured the connection with the IdP of your choice. If not, go to [Identity Providers Supported by Auth0](/identityproviders), select the IdP you want, and follow the configuration steps.
:::
-The process you will follow differs, depending on whether your code runs in the backend or the frontend:
+The process you will follow differs depending on whether your code runs in the backend or the frontend:
-- If your code runs in the backend then we can assume that your server is trusted to safely store secrets (as you will see, we use a secret in the backend scenario). If that's the case proceed to the [backend section](#from-the-backend) of this article.
+- If your code runs in the backend, then we can assume that your server is trusted to safely store secrets (as you will see, we use a secret in the backend scenario). If that's the case, proceed to the [backend section](#from-the-backend) of this article.
-- If your code runs in the frontend (for example, it's a SPA, native desktop, or mobile app) then your app cannot hold credentials securely and has to follow an alternate approach. To see your options proceed to the [frontend section](#from-the-frontend) of this article.
+- If your code runs in the frontend (for example, it's a SPA, native desktop, or mobile app), then your app cannot hold credentials securely and has to follow an alternate approach. In this case, proceed to the [frontend section](#from-the-frontend) of this article.
## From the backend
-Once you authenticate a user, the IdP often includes an Access Token in the user profile it returns to Auth0.
+Once you authenticate a user, the IdP often includes an Access Token in the user profile it returns to Auth0.
-Auth0, for security and compliance reasons, does **not** sent this token to your app as part of the user profile. In order to get it you will have to access the Auth0 Management API and retrieve the **full** user's profile.
-
-The steps to follow are:
+For security and compliance reasons, Auth0 does not send this token to your app as part of the user profile. To get it, you must access the Auth0 Management API and retrieve the full user's profile:
1. Get an Access Token that allows you to call the [Auth0 Management API](/api/management/v2).
-2. Call the Auth0 Management API's [Get Users by ID](/api/management/v2#!/Users/get_users_by_id) endpoint, using the Access Token obtained in step one. This endpoint returns the full user's profile, which contains the IdP Access Token.
+
+2. Call the Auth0 Management API's [Get Users by ID endpoint](/api/management/v2#!/Users/get_users_by_id) using the Access Token obtained in step one. This endpoint returns the full user's profile, which contains the IdP Access Token.
+
3. Extract the IdP Access Token from the response and use it to call the IdP's API.
### Step 1: Get a Token
You will need an Access Token to call the [Management API](/api/management/v2).
-If this is the first time you are requesting a [Management APIv2 Token](/api/management/v2/tokens), you will need to create and configure an application that can be used to call the API.
+#### Create a test application for the Management API
-To do so, go to [Dashboard > APIs > Auth0 Management API > API Explorer](${manage_url}/#/apis/management/explorer) and click **Create & Authorize a Test Application**.
+If this is the first time you are requesting a [Management APIv2 Token](/api/management/v2/tokens), you will need to create and configure an application that can be used to call the Management API:
-This will create a new application and grant **all scopes of the Management API**. This means that the tokens generated for this application will be able to access **all Management API endpoints**.
+1. Navigate to [Auth0 Dashboard > Applications > APIs](${manage_url}/#/apis/, and select the [Auth0 Management API](${manage_url}/#/apis/management/authorized-clients).
+
+2. Select the **API Explorer** view, and click **Create & Authorize a Test Application**.
+
+This will create a new application and grant **all scopes of the Management API**. This means that the tokens generated for this application will be able to access **all Management API endpoints**.
::: panel Can't see the button?
-If you don't see this button, it means that you have at least one authorized application already. In this case you can either update the scopes of an existing application and use that, or create a new one following these steps:
-1. Go to [Dashboard > Applications](${manage_url}/#/applications)
-2. Click **+ Create Application**, select **Non Interactive Applications** and click **Create**
-3. At the **Select an API** dropdown select `Auth0 Management API`
-4. Click **Navigate to the API and Authorize**
-5. Set the toggle to **Authorized** and enable the required scopes
+If you don't see this button, it means that you already have at least one authorized application for the Management API. In this case, you can either update the scopes of the existing application and use that, or create a new one following these steps:
+
+1. Navigate to [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications), and click **Create Application**.
+2. Select **Machine to Machine Applications**, and then **Create**
+3. From the **Select an API** dropdown, select `Auth0 Management API`.
+4. Enable required scopes, and select **Authorize**.
+5. Select the **APIs** view, and enable the toggle for **Auth0 Management API**.
:::
-It is recommended, for security reasons, that you only assign the required scopes to the application you will be using. For this particular case, the scopes you need are: `read:users`, `read:user_idp_tokens`.
+::: warning Security
+For security reasons, we recommend that you assign only the required scopes to the application you will be using. For this particular case, the scopes you need are: `read:users`, `read:user_idp_tokens`. Required scopes are listed for each endpoint in the [Management API Explorer](/api/management/v2/).
+:::
+
+To grant or remove scopes from the [registered Auth0 Management API](${manage_url}/#/apis/management/authorized-clients), select the [**Machine to Machine Applications** view](${manage_url}/#/apis/management/authorized-clients):
+
+
-You can grant or remove scopes from an application, at the [Dashboard > APIs > Auth0 Management API > Non Interactive Applications tab](${manage_url}/#/apis/management/authorized-applications).
+#### Get the Management API Token
-
+You are now done with configuration and are ready to get your Management API token:
-You are now done with the configuration part, and you are ready to get your Management API token.
+1. From the [registered Auth0 Management API](${manage_url}/#/apis/management/authorized-clients), select the [Test view](${manage_url}/#/apis/management/test).
-To do so, go to the [Test tab](${manage_url}/#/apis/management/test). There you can find ready-to-use snippets that you can use to get a token.
+2. Choose your application from the **Application** dropdown to pre-populate the ready-to-use snippets with customized variables.
-Pick your application using the dropdown at the top, and choose your language of preference for the snippet.
+3. Choose your language of preference for the snippet, and copy and run it.
-Copy and run the snippet. Extract the `access_token` property from the response. This is what you will use to access the Management API.
+4. Extract the `access_token` property from the response. This is what you will use to access the Management API.
-::: panel More info on the snippets
-The snippets make a `POST` operation to the [/oauth/token endpoint of the Auth0 Authentication API](/api/authentication#client-credentials), using the **OAuth 2.0 Client Credentials grant**. This is the grant that machine-to-machine processes utilize in order to access an API. For more information on the grant, refer to [Calling APIs from a Service](/api-auth/grant/client-credentials).
+::: panel What are the snippets doing?
+The snippets make a `POST` operation to the [/oauth/token endpoint of the Auth0 Authentication API](/api/authentication#client-credentials), using the **OAuth 2.0 Client Credentials grant**. This is the grant that machine-to-machine processes use to access an API. To learn more about the flow, refer to [Client Credentials Flow](/flows/concepts/client-credentials).
:::
#### Token expiration
-The token you received has, by default, an expiration time of 24 hours (86400 seconds). To change this, update the **Token Expiration (Seconds)** field, at the [Settings tab](${manage_url}/#/apis/management/settings) and save your changes. The next token you generate will use the updated expiration time.
+By default, the token you received expires in 24 hours (86400 seconds). To change this:
+
+1. Navigate to [Auth0 Dashboard > Applications > APIs](${manage_url}/#/apis/, and select the [Auth0 Management API](${manage_url}/#/apis/management/authorized-clients).
+
+2. Select the **Settings** view, locate the **Token Expiration (Seconds)** field, enter a new value, and click **Save**. The maximum value you can set is 2592000 seconds (30 days), though we recommend that you keep the default value.
+
+The next token you generate will use the updated expiration time.
::: panel-warning Security warning
-These tokens **cannot be revoked**. To minimize the risk, we recommend issuing short-lived tokens (and granting only the necessary scopes for each application). For a production environment you can configure a simple CLI that will fetch a new token when the old one expires. You can find a sample implementation in Python [here](/api/management/v2/tokens#sample-implementation-python).
+These tokens **cannot be revoked**. To minimize risk, we recommend issuing short-lived tokens and granting only the necessary scopes for each application. For a production environment, you can configure a simple CLI that will fetch a new token when the old one expires.
:::
### Step 2: Get the full User Profile
-Using the Access Token you got in the previous section, call the [Get a User endpoint of the Management API](/api/management/v2#!/Users/get_users_by_id), in order to get a user's profile:
+To get a user's profile, call the [Get a User endpoint](/api/management/v2#!/Users/get_users_by_id) of the Management API using the Access Token you extracted in the previous section:
```har
{
@@ -95,26 +121,25 @@ Using the Access Token you got in the previous section, call the [Get a User end
```
Replace these values:
-- `USER_ID`: The ID of the user for whom you want to call the IdP's API.
-- `YOUR_ACCESS_TOKEN`: The token you got from the previous step.
+- `USER_ID`: ID of the user for whom you want to call the IdP's API.
+- `YOUR_ACCESS_TOKEN`: Access Token you extracted in the previous section.
::: panel Where do I find the User ID?
-- For testing purposes, you can find a user ID at [Dashboard > Users](${manage_url}/#/users/). Select a user and copy the value of the **user_id** field.
-- For your implementation, you can either extract this information from the [ID Token](/tokens/id-token) (get the value of the claim **sub**), or call the [/userinfo endpoint of the Authentication API](/api/authentication#get-user-info) (get the value of the response property **user_id**).
+- For testing purposes, you can find a user ID at [Auth0 Dashboard > User Management > Users](${manage_url}/#/users/). Locate a user, and copy the value of the **user_id** field.
+- For your implementation, you can either extract the user ID from the `sub` claim in the [ID Token](/tokens/concepts/id-tokens), or call the [/userinfo endpoint](/api/authentication#get-user-info) of the Authentication API and extract it from the `user_id` response property.
:::
-
### Step 3: Extract the IdP Access Token
-Within the user's `identities` array, there will be an `access_token` that you can extract and use to make calls to the IdP's API: `user.identities[0].access_token`.
+You can find the Access Token used to call the IdP's API within the user's `identities` array: `user.identities[0].access_token`.
::: note
-For certain Identity Providers, Auth0 will store a `refresh_token` which you can use to obtain a new `access_token` for the IdP. This works for: BitBucket, Google (OAuth 2.0), OAuth 2.0, SharePoint, Azure AD. For more information, refer to [Identity Provider Access Tokens](/tokens/idp#renewing-the-token).
+For certain Identity Providers, Auth0 will also store a Refresh Token, which you can use to obtain a new Access Token for the IdP. This works for: BitBucket, Google (OAuth 2.0), OAuth 2.0, SharePoint, and Azure AD. To learn more, see [Identity Provider Access Tokens](/tokens/concepts/idp-access-tokens#renew-tokens).
:::
-In most cases, the user will only have one identity, but if you have used the [account linking feature](/link-accounts), there may be more.
+In most cases, the user will only have one identity, but if the user has signed in multiple times through different connections and you have used [account linking](/users/concepts/overview-user-account-linking), there may be more.
-In this sample response we can see that our user had only one identity: `google-oauth2`.
+In this sample response, we see that our user has only one identity: `google-oauth2`.
```json
{
@@ -149,57 +174,33 @@ In this sample response we can see that our user had only one identity: `google-
You are now ready to call the IdP's API. Please refer to the IdP's documentation for specifics on how to do so.
::: warning
-Make sure that you don't expose the IdP tokens to your client-side application! If your application is public refer to the [frontend section](#from-the-frontend) of this article.
+Don't expose IdP tokens to your client-side application! If your application is public, see the [frontend section](#from-the-frontend) of this article.
:::
::: note
-For more information on how to request specific scopes for an Identity Provider `access_token`, please see [Add scopes/permissions to call Identity Provider's APIs](/tutorials/adding-scopes-for-an-external-idp).
+To learn more about how to request specific scopes for an Identity Provider Access Token, please see [Add scopes/permissions to call Identity Provider's APIs](/connections/adding-scopes-for-an-external-idp).
:::
## From the frontend
-If you are working with a public application (SPA, native desktop, or mobile app) then this is the place to be.
-
-As you might have read earlier in this article, the process for calling IdP APIs from a **backend process** includes the following steps:
-
-1. Get an Access Token in order to access the Auth0 Management API
-2. Use said token to retrieve the user's full profile from the Auth0 Management API
-3. Extract the IdP's Access Token from the user's full profile, and use it to call the IdP's API
+If you are working with a public application (SPA, native desktop, or mobile app), then this is the place to be.
-You cannot follow the same process from a frontend app because it's a public application that **cannot hold credentials securely**. The credential we are referring to, is the machine to machine application's secret which you use to make the call to `/oauth/token`, at the first step of the process.
+When working with a frontend app, the process for calling IdP APIs differs from the backend process because frontend apps are public applications that **cannot hold credentials securely**. Because SPA code can be viewed and altered, and native/mobile apps can be decompiled and inspected, they cannot be trusted to hold sensitive information like secret keys or passwords.
-SPA's code can be viewed and altered and native/mobile apps can be decompiled and inspected. As such, they cannot be trusted to hold sensitive information like secret keys or passwords.
+Specifically, they cannot securely hold the **Client Secret** for the Machine to Machine Application, which you use to call `/oauth/token` during the first step of the backend process.
-There are some alternatives you can use.
+Instead, you must build a proxy for your backend and expose it to your application as an API.
-### Option 1: Build a proxy
+### Build a proxy
-You can build a process in your backend and expose it to your application as an API.
+First, you will build a process in your backend that will implement the steps included in [the backend section](#from-the-backend) of this article, and expose it to your application as an API.
-The backend process will implement the steps of [the backend section](#from-the-backend). You will call the IdP's API from the same backend process so the Access Token is never exposed to your public application.
-
-Then, you will call your proxy API from your public application using the respective flow for your case:
-- [Implicit Grant](/api-auth/tutorials/implicit-grant) if you are working with a SPA
-- [Authorization Code Grant (PKCE)](/api-auth/tutorials/authorization-code-grant-pkce) if you are working with a mobile application
-
-:::panel Show me how to do it
-If you haven't implemented this before, you might find our [SPA + API](/architecture-scenarios/application/spa-api) article useful. It covers a different scenario but it does explain how to configure Auth0, call an API from a SPA, and implement the API validations. It comes with a sample that uses [Angular 2](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-spa/angular) and [Node.js](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node). We also offer a [Mobile + API](/architecture-scenarios/application/mobile-api) variation (the sample uses [Android](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-mobile/android) and [Node.js](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node)).
-:::
-
-### Option 2: Use webtasks
-
-If you don't have a backend server, and you don't want to set up one, then you can leverage serverless technology, using webtasks.
-
-Webtasks are the Auth0 way to create HTTP endpoints with Node.js and access them from anywhere. It's a way to safely execute server-side logic, when you do not have a backend. They come with a command line tool and an editor. For more information refer to [the webtask.io documentation](https://webtask.io/).
-
-:::note
-This option comes with an additional cost, for details see [Auth0 Extend pricing](https://auth0.com/extend/pricing).
-:::
+You will call the IdP's API from the same backend process, so the Access Token is never exposed to your public application.
-In this scenario, you will create a webtask and implement the steps of [the backend section](#from-the-backend). Then the webtask will call the IdP's API so the Access Token is never exposed to your public application.
+Then, you will call your proxy API from your public application using the [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/guides/auth-code-pkce/call-api-auth-code-pkce).
-Your application will invoke the webtask with a simple HTTP request and manipulate the response appropriately (for example, render the user's GitHub repositories in the UI).
+:::panel Show me how
+If you haven't implemented this before, you might find our [SPA + API](/architecture-scenarios/application/spa-api) article useful. It covers a different scenario, but it explains how to configure Auth0, how to call an API from a SPA, and how to implement API validations. It comes with a sample that uses [Angular 2](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-spa/angular) and [Node.js](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node).
-:::note
-You can find a sample [in this GitHub repository](https://github.com/vikasjayaram/ext-idp-api-webtask/tree/master/RS256). Review carefully before you use it since this is not officially maintained by Auth0 and could be outdated.
+We also offer a [Mobile + API](/architecture-scenarios/application/mobile-api) variation (the sample uses [Android](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-mobile/android) and [Node.js](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets/tree/master/timesheets-api/node)).
:::
diff --git a/articles/connections/criipto/bankid-no.md b/articles/connections/criipto/bankid-no.md
index 36f383debb..a2ed575ad4 100644
--- a/articles/connections/criipto/bankid-no.md
+++ b/articles/connections/criipto/bankid-no.md
@@ -6,6 +6,13 @@ seo_alias: bankid
description: Connecting Norwegian BankID with Auth0 through the Criipto Verify service
toc: true
crews: crew-2
+topics:
+ - connections
+ - criipto
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Log in with Norwegian BankID through Auth0
@@ -15,7 +22,7 @@ you may avoid the integration trouble.
Below is an outline of the steps to get ready to accept Norwegian BankID logins, but you may also view [a short screen cast](https://criipto.com/easyid/auth0/2016/12/07/easyid-and-auth0/) at Criipto's website.
-::: panel Process to use NOrwegian BankID in Production
+::: panel Process to use Norwegian BankID in Production
While the technical integration complexity is simple, to use Norwegian BankID in production you will have to go through a formal process to
register and obtain the necessary certificate to identify yourself to your users.
More on this process can be found once you sign into the Criipto Verify service, and with the help of Criipto.
@@ -64,7 +71,7 @@ Click the check mark in the green area at the bottom to allow Criipto Verify to
## 5. Verify the connections
-Go to the **Connections > Enterprise** section and open the **ADFS** connections to see the connections for Norwegian BankID created from the previous steps.
+Go to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and open the **ADFS** connections to see the connections for Norwegian BankID created from the previous steps.
::: note
One connection has been created for each kind of authentication supported by Norwegian BankID: Browser based and mobile. The mobile method requires a special SIM card issued by a Norwegian provider.
diff --git a/articles/connections/criipto/bankid-se.md b/articles/connections/criipto/bankid-se.md
index 101ec61b86..d8f6ad3466 100644
--- a/articles/connections/criipto/bankid-se.md
+++ b/articles/connections/criipto/bankid-se.md
@@ -6,6 +6,13 @@ seo_alias: bankid
description: Connecting Swedish BankID with Auth0 through the Criipto Verify service
toc: true
crews: crew-2
+topics:
+ - connections
+ - criipto
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Log in with Swedish BankID through Auth0
@@ -65,7 +72,7 @@ Click the check mark in the green area at the bottom to allow Criipto Verify to
## 5. Verify the connections
-Go to the **Connections > Enterprise** section and open the **ADFS** connections to see the connections for
+Go to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and open the **ADFS** connections to see the connections for
Swedish BankID created from the previous steps.
::: note
diff --git a/articles/connections/criipto/nemid.md b/articles/connections/criipto/nemid.md
index 0287a22c98..31d793e530 100644
--- a/articles/connections/criipto/nemid.md
+++ b/articles/connections/criipto/nemid.md
@@ -6,6 +6,13 @@ seo_alias: nemid
description: Connecting Danish NemID with Auth0 through the Criipto Verify service
toc: true
crews: crew-2
+topics:
+ - connections
+ - criipto
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Log in with Danish NemID through Auth0
@@ -20,7 +27,7 @@ Below is an outline of the steps to get ready to accept Danish NemID logins, but
[a short screen cast](https://criipto.com/easyid/auth0/2016/12/07/easyid-and-auth0/) at Criipto's website.
::: panel Process to use Swedish BankID in Production
-While the technical integration is simple, to use Danish NemID in production you will have to go through a formal process to register and obtain the necessary certificate to identify yourself to your users. This proces must be completed with the Danish NemID operator, Nets.
+While the technical integration is simple, to use Danish NemID in production you will have to go through a formal process to register and obtain the necessary certificate to identify yourself to your users. This process must be completed with the Danish NemID operator, Nets.
More on this process can be found once you sign into the Criipto Verify service, and with the help of Criipto.
:::
@@ -67,7 +74,7 @@ Click the check mark in the green area at the bottom to allow Criipto Verify to
## 5. Verify the connections
-Go to the **Connections > Enterprise** section and open the **ADFS** connections to see the connections for
+Go to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and open the **ADFS** connections to see the connections for
Danish NemID created from the previous steps.
::: note
diff --git a/articles/connections/database/auth0-user-store.md b/articles/connections/database/auth0-user-store.md
new file mode 100644
index 0000000000..d009b0ddc1
--- /dev/null
+++ b/articles/connections/database/auth0-user-store.md
@@ -0,0 +1,24 @@
+---
+title: Auth0 User Store
+description: Describes creating and using a database connection with the Auth0 user store.
+topics:
+ - connections
+ - database
+ - db-connections
+useCase:
+ - customize-connections
+---
+
+# Auth0 User Store
+
+Auth0 provides the database infrastructure to store your users by default. This scenario provides the best performance for the authentication process since all data is stored in Auth0.
+
+The Auth0-hosted database is highly secure. Passwords are never stored or logged in plain text but are hashed with **bcrypt**. Varying levels of password security requirements can also be enforced. To learn more, read [Password Strength in Auth0 Database Connections](/password-strength).
+
+::: note
+For database connections, Auth0 limits the number of repeat login attempts per user and IP address. To learn more, read [Rate Limits on User/Password Authentication](/policies/rate-limit-policy/database-connections-rate-limits).
+:::
+
+## Migrating to Auth0 from a custom user store
+
+In this scenario, you have a legacy user store and wish to switch to the Auth0 store. Auth0 provides an automatic migration feature that adds your users to the Auth0 database one-at-a-time as each logs in and avoids asking your users to reset their passwords all at the same time. To learn more, read [Configure Automatic User Migration](/users/guides/configure-automatic-migration).
\ No newline at end of file
diff --git a/articles/connections/database/custom-db.md b/articles/connections/database/custom-db.md
deleted file mode 100644
index 303b4bebfc..0000000000
--- a/articles/connections/database/custom-db.md
+++ /dev/null
@@ -1,183 +0,0 @@
----
-title: Authenticate Users Using Your Database
-connection: MySQL
-image: /media/connections/mysql.svg
-seo_alias: mysql
-description: Learn how to authenticate users using your database as an identity provider.
-crews: crew-2
-toc: true
----
-
-# Authenticate Users Using Your Database
-
-If you have your own user database, you can use that database as an identity provider in Auth0 to authenticate users. To set up and use your database for authentication you'll need to:
-
-* Create a [database connection](/connections/database) on the [Auth0 dashboard](${manage_url}).
-* Ensure your database has fields to populate user profiles such as: `id`, `nickname`, `email`, and `password`. See [Auth0 Normalized User Profile](/user-profile/normalized) for details on Auth0's user profile schema and expected fields.
-* Provide database action scripts to configure the database as an identity provider.
-
-In this tutorial you'll learn how to connect your user database to Auth0 and configure it as an identity provider.
-
-## Before You Begin
-
-Here are some things to know before you start this process.
-
-* Database action scripts are written in Javascript and run in a [Webtask](https://webtask.io/) environment. In the environment you can use the full JavaScript language and [these Node.js libraries](https://tehsis.github.io/webtaskio-canirequire/).
-* Auth0 provides templates for most common databases, such as: **ASP.NET Membership Provider**, **MongoDB**, **MySQL**, **Oracle**, **PostgreSQL**, **SQLServer**, **Windows Azure SQL Database**, and for a web service accessed by **Basic Auth**. Essentially, you can connect to any kind of database or web service with a custom script.
-* You can use the [auth0-custom-db-testharness library](https://www.npmjs.com/package/auth0-custom-db-testharness) to deploy, execute, and test the output of database action scripts using a Webtask sandbox environment.
-* The [Update Users Using Your Database](/user-profile/customdb) article has information on updating user profile fields.
-
-## Create the database connection
-
-To create the database connection for your database, follow these steps.
-
-1. Navigate to [Connections > Database](${manage_url}/#/connections/database) on the Auth0 dashboard.
-2. Click the **+ Create DB Connection** button.
-3. Provide a name for the database and configure the available options.
-
-
-
-3. Navigate to the **Custom Database** tab.
-4. Toggle on the **Use my own database** switch.
-
-
-
-## Create database action scripts
-
-Create scripts in the **Database Action Scripts** section to configure how authentication works when using your database.
-
-A Login script is required. Additional scripts for user functionality, such as password resets, are optional. You can write your own scripts or select a template from the **Templates** dropdown and adjust it to your requirements.
-
-The available actions are:
-
-Name | Description | Parameters
--------|-------------|-----------
-Login (Required) | Executes each time a user attempts to log in. | `email`, `password`
-Create | Executes when a user signs up. | `user.email`, `user.password`
-Verify | Executes after a user follows the verification link. | `email`
-Change Password | Executes when a user clicks on the confirmation link after a reset password request. | `email`, `newPassword`
-Get User | Retrieves a user profile from your database without authenticating the user. | `email`
-Delete | Executes when a user is deleted from the API or Auth0 dashboard. | `id`
-
-::: note
-When creating users, Auth0 calls the **Get User** script before the **Create** script. Be sure that you have implemented both.
-:::
-
-### Create the Login script
-
-The Login script will run each time a user attempts to log in. You can write your own Login script or select a template from the **Templates** dropdown.
-
-::: note
-If you are using [IBM's DB2](https://www.ibm.com/analytics/us/en/technology/db2/) product, [click here](/connections/database/db2-script) for a sample login script.
-:::
-
-
-
-For example, the MySQL Login template:
-
-```js
-function login(email, password, callback) {
- var connection = mysql({
- host: 'localhost',
- user: 'me',
- password: 'secret',
- database: 'mydb'
- });
-
- connection.connect();
-
- var query = "SELECT id, nickname, email, password " +
- "FROM users WHERE email = ?";
-
- connection.query(query, [email], function (err, results) {
- if (err) return callback(err);
- if (results.length === 0) return callback(new WrongUsernameOrPasswordError(email));
- var user = results[0];
-
- bcrypt.compare(password, user.password, function (err, isValid) {
- if (err) {
- callback(err);
- } else if (!isValid) {
- callback(new WrongUsernameOrPasswordError(email));
- } else {
- callback(null, {
- id: user.id.toString(),
- nickname: user.nickname,
- email: user.email
- });
- }
- });
-
- });
-}
-
-```
-
-The above script connects to a MySQL database and executes a query to retrieve the first user with `email == user.email`. With the `bcrypt.compareSync` method, it then validates that the passwords match, and if successful, returns an object containing the user profile information including `id`, `nickname`, and `email`. This script assumes that you have a `users` table containing these columns. Note that `id` returned by Login script is used to construct `user_id` attribute of user profile. If you are using multiple custom database connections then value of `id` must be unique across all the custom database connections to avoid and `user_id` collisions. Our recommendation is to prefix the value of `id` with connection name without any whitespace in the resulting value.
-
-## Add configuration parameters
-
-You can store parameters, like the credentials required to connect to your database, in the Settings section below the script editor. These will be available to all of your scripts and you can access them using the global configuration object.
-
-You can access parameter values using the `configuration` object in your database action scripts, for example: `configuration.MYSQL_PASSWORD`.
-
-
-
-Use the added parameters in your scripts to configure the connection. For example, in the MySQL Login template:
-
-```js
-function login (username, password, callback) {
- var connection = mysql({
- host : configuration.MYSQL_HOST,
- user : 'me',
- password : configuration.MYSQL_PASSWORD,
- database : 'mydb'
- });
-}
-```
-
-## Error Handling
-
-There are three different errors you can return from a database connection:
-
-* `new WrongUsernameOrPasswordError(, )`: when you know who the user is and want to keep track of a wrong password.
-* `new ValidationError(, )`: a generic error with an error code.
-* `new Error()`: simple errors (no error code).
-
-To return an error, call the callback with an error as the first parameter:
-
-```js
-callback(error);
-```
-
-For example:
-
-```js
-callback(new ValidationError('email-too-long', 'Email is too long.'));
-```
-
-If you use [Lock](/libraries/lock), you can customize the error messages that will be displayed by adding them to the dictionary. For more info, see [Customizing Lock Error Messages](libraries/lock/customizing-error-messages).
-
-## Metadata
-
-Depending on your custom database script, you may return a user profile to Auth0 apps. This profile includes the user metadata fields. The **app_metadata** field(s) should be [referred to as **metadata** in scripts for custom databases](/metadata#metadata-and-custom-databases).
-
-## Troubleshoot
-
-Test the script using the **TRY** button. If your settings are correct you should see the resulting profile:
-
-
-
-If you do not get the expected result or receive an error, use `console.log`statements in your script and try the connection again. The output of `console.log` prints in the try the script window.
-
-::: note
-The [auth0-custom-db-testharness library](https://www.npmjs.com/package/auth0-custom-db-testharness) can be used to deploy, execute, and test the output of database action scripts using a Webtask sandbox environment.
-:::
-
-## Auth0 Login widget
-
-If you use [Lock](libraries#lock), enabling the database connection lets users enter their username and password on the Auth0 Login widget. Once entered, this data is passed to your scripts.
-
-
-
-<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/database/custom-db/_includes/_bp-error-object.md b/articles/connections/database/custom-db/_includes/_bp-error-object.md
new file mode 100644
index 0000000000..19e3e9c3a1
--- /dev/null
+++ b/articles/connections/database/custom-db/_includes/_bp-error-object.md
@@ -0,0 +1,3 @@
+::: panel Best practice
+When indicating an error, we recommend using the `Error` object to provide Auth0 with a clear indication of the error condition. For example, use `callback(new Error(“an error message”))` when a problems occurs with communication to your database. See [Types of errors](/connections/database/custom-db/error-handling#types-of-errors) for more information.
+:::
diff --git a/articles/connections/database/custom-db/_includes/_panel-bcrypt-hash-encryption.md b/articles/connections/database/custom-db/_includes/_panel-bcrypt-hash-encryption.md
new file mode 100644
index 0000000000..461e7d01a6
--- /dev/null
+++ b/articles/connections/database/custom-db/_includes/_panel-bcrypt-hash-encryption.md
@@ -0,0 +1,14 @@
+::: panel `bcrypt` hash encryption
+The password credential for the user is passed to the login script in plain text so care must be taken regarding its use. You should refrain from logging, storing, or transporting the `password` credential anywhere in its vanilla form. Instead, use something similar to the following example, which uses the `bcrypt` algorithm to perform cryptographic hash encryption:
+
+```js
+bcrypt.hash(password, 10, function (err, hash) {
+ if (err) {
+ return callback(err);
+ } else {
+ .
+ .
+ }
+});
+```
+:::
diff --git a/articles/connections/database/custom-db/_includes/_panel-feature-availability.md b/articles/connections/database/custom-db/_includes/_panel-feature-availability.md
new file mode 100644
index 0000000000..94cac832e0
--- /dev/null
+++ b/articles/connections/database/custom-db/_includes/_panel-feature-availability.md
@@ -0,0 +1,3 @@
+::: panel Limited Access
+Your Auth0 subscription plan affects the availability of some features. For more information, see [Auth0 pricing plans](https://auth0.com/pricing).
+:::
diff --git a/articles/connections/database/custom-db/create-db-connection.md b/articles/connections/database/custom-db/create-db-connection.md
new file mode 100644
index 0000000000..9f1e1d9862
--- /dev/null
+++ b/articles/connections/database/custom-db/create-db-connection.md
@@ -0,0 +1,170 @@
+---
+description: Learn how to create a database connection.
+toc: true
+topics:
+ - connections
+ - custom-database
+contentType: how-to
+useCase: customize-connections
+---
+# Create Custom Database Connections
+
+<%= include('./_includes/_panel-feature-availability') %>
+
+If you have your own user database, you can use it as an identity provider in Auth0 to authenticate users. In this process, you will create the custom database connection, create database action scripts, and add configuration parameters.
+
+::: note
+Make sure that your database has the appropriate fields to store user profiles attributes, such as **id**, **nickname**, **email**, and **password**. See [Normalized User Profile](/users/normalized) for details on Auth0's user profile schema and the expected fields. Also, see [Update User Profile Using Your Database](/users/guides/update-user-profiles-using-your-database) for more information.
+:::
+
+Auth0 allows you to create connections and scripts for most of the commonly-used databases, including:
+
+ * ASP.NET Membership Provider
+ * MongoDB
+ * MySQL
+ * PostgreSQL
+ * SQLServer
+ * Windows Azure SQL Database
+ * Web services accessed via Basic Auth
+
+You can connect to any kind of database or web service with a properly-configured custom script.
+
+<%= include('../../../_includes/_ip_whitelist') %>
+
+## Create the connection in the Auth0 Dashboard
+
+1. Navigate to [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database), and select **+ Create DB Connection**.
+
+ 
+
+2. Configure the connection's settings, and click **Create**:
+
+ | **Parameter** | **Definition** |
+ | - | - |
+ | **Name** | The name of the connection. The name must start and end with an alphanumeric character, contain only alphanumeric characters and dashes, and not exceed 35 characters. |
+ | **Requires Username** | Forces users to provide a username *and* email address during registration. |
+ | **Username length** | Sets the minimum and maximum length for a username. |
+ | **Disable Sign Ups** | Prevents sign-ups to your application. You will still be able to create users with your API credentials or via the Auth0 Dashboard. |
+
+ Once Auth0 creates your connection, you'll have the following views (in addition to the **Settings** view):
+
+ * Password Policy
+ * Custom Database
+ * Applications
+ * Try Connection
+
+3. Select the **Custom Database** view, and enable the **Use my own database** switch.
+
+ 
+
+## Create database action scripts
+
+Toggling the **Use my own database** switch enables the **Database Action Scripts** area where you will create scripts to configure how authentication works when using your database. You can write your database action scripts, or you can select a template from the **Templates** dropdown and modifying it as necessary.
+
+You **must** configure a `login` script; additional scripts for user functionality are optional.
+
+The available database action scripts are:
+
+**Name** | **Description** | **Parameters**
+-------|-------------|-----------
+**Login** Required | Executes each time a user attempts to log in. | `email`, `password`
+**Create** | Executes when a user signs up. | `user.email`, `user.password`
+**Verify** | Executes after a user follows the verification link. | `email`
+**Change Password** | Executes when a user clicks on the confirmation link after a reset password request. | `email`, `newPassword`
+**Get User** | Retrieves a user profile from your database without authenticating the user. | `email`
+**Delete** | Executes when a user is deleted using the API or Auth0 Dashboard. | `id`
+**Change Email** | Executes when a change in the email address, or the email address status, for a user occurs. | `email`, `newEmail`, `verified`, `callback`
+
+See [Custom Database Action Script Templates](/connections/database/custom-db/templates) and [Custom Database Action Script Execution Best Practices](/best-practices/custom-db-connections/execution) for details on all the scripts.
+
+### Create a Login script
+
+::: panel Avoid User ID Collisions with Multiple Databases
+The `id` (or alternatively `user_id`) property in the returned user profile will be used by Auth0 to identify the user.
+
+If you are using multiple custom database connections, then **id** value **must be unique across all the custom database connections** to avoid **user ID** collisions. Our recommendation is to prefix the value of **id** with the connection name (omitting any whitespace). See [Identify Users](/users/normalized/auth0/identify-users) for more information on user IDs.
+:::
+
+The following steps use an example for a MySQL database login script.
+
+1. After toggling the **Use my own database** switch, the **Database Action Scripts** area is enabled. Make sure you are on the **Login** tab.
+3. Use the **Templates** dropdown to select the MySQL database script template.
+
+```js
+function login(email, password, callback) {
+ var bcrypt = require('bcrypt');
+ var mysql = require('mysql');
+
+ var connection = mysql.createConnection({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret',
+ database: 'mydb'
+ });
+
+ connection.connect();
+
+ var query = "SELECT id, nickname, email, password " +
+ "FROM users WHERE email = ?";
+
+ connection.query(query, [email], function (err, results) {
+ if (err) return callback(err);
+ if (results.length === 0) return callback(new WrongUsernameOrPasswordError(email));
+ var user = results[0];
+
+ bcrypt.compare(password, user.password, function (err, isValid) {
+ if (err) {
+ callback(err);
+ } else if (!isValid) {
+ callback(new WrongUsernameOrPasswordError(email));
+ } else {
+ callback(null, {
+ // This prefix (replace with your own custom DB name)
+ // ensure uniqueness across different custom DBs if there's the
+ // possibility of collisions (e.g. if the user ID is an email address or an integer)
+ id: 'MyConnection1|' + user.id.toString(),
+ nickname: user.nickname,
+ email: user.email
+ });
+ }
+ });
+ });
+}
+```
+
+The above script connects to a MySQL database and executes a query to retrieve the first user with `email == user.email`.
+
+With the **bcrypt.compareSync** method, it then validates that the passwords match, and if successful, returns an object containing the user profile information including **id**, **nickname**, and **email**.
+
+This script assumes that you have a **users** table containing these columns. The **id** returned by Login script is used to construct the **user ID** attribute of the user profile.
+
+4. Click **Save**.
+5. Click **Try** to test the script. (This step will also save your script.)
+
+ Script templates are not used by Auth0 until you click **Save** or **Try**. This is true even if you only modify one script and haven't made changes to any others. You must click **Save** at least once for all the scripts to be in place.
+
+## Add configuration parameters
+
+You can store parameters, like the credentials required to connect to your database, in the **Settings** section below the script editor. These will be available for all of your scripts, and you can access the parameter values using the `configuration` object in your database action scripts (i.e., `configuration.MYSQL_PASSWORD`).
+
+
+
+Use the added parameters in your scripts to configure the connection. For example, you might add the following to the MySQL Login script:
+
+```js
+function login (username, password, callback) {
+ var mysql = require('mysql');
+ var connection = mysql.createConnection({
+ host : configuration.MYSQL_HOST,
+ user : 'me',
+ password : configuration.MYSQL_PASSWORD,
+ database : 'mydb'
+ });
+}
+```
+
+## Keep reading
+
+* [Custom Database Connection and Action Script Best Practices](/best-practices/custom-db-connections)
+* [Custom Database Error Handling and Troubleshooting](/connections/database/custom-db/error-handling)
+* [Migrate Users to Auth0](/users/concepts/overview-user-migration)
diff --git a/articles/connections/database/custom-db/error-handling.md b/articles/connections/database/custom-db/error-handling.md
new file mode 100644
index 0000000000..654f9f1c4a
--- /dev/null
+++ b/articles/connections/database/custom-db/error-handling.md
@@ -0,0 +1,51 @@
+---
+description: Describes how to handle errors and troubleshoot when using your database as an identity provider.
+topics:
+ - connections
+ - custom-database
+ - troubleshooting
+contentType: reference
+useCase:
+ - customize-connections
+ - troubleshooting
+---
+# Troubleshoot Custom Databases
+
+You can use return errors resulting from your custom database connection for troubleshooting purposes. We will also cover some basic troubleshooting steps for your scripts.
+
+## Types of errors
+
+There are three different errors you can return from a database connection:
+
+| Error | Login Script | Description |
+| - | - | - |
+| `new WrongUsernameOrPasswordError(, )` | Login | Occurs when the user's credentials are invalid |
+| `new ValidationError(, )` | Create | Occurs when a user already exists in your database |
+| `callback(,)` | Change Password | Occurs when the user's password was not updated|
+| `callback()` | Get User | Occurs when the user is not found|
+| `new Error()` | All Login Scripts | Occurs when something went wrong while trying to reach the database |
+
+## Return errors
+
+To return an error, call the **callback** function while passing **error** as the first parameter:
+
+```js
+callback(error);
+```
+
+**Example:**
+
+```js
+callback(new ValidationError('email-too-long', 'Email is too long.'));
+```
+
+### Returning errors when using Lock
+
+If you use Lock, you can [customize the error messages](libraries/lock/customizing-error-messages) that will be displayed by adding them to the dictionary.
+
+## Troubleshooting Errors
+
+Test the script using the **TRY** button.
+
+If you do not get the expected result or you receive an error, install the [Real-time Webtask Logs extension](/extensions/realtime-webtask-logs) and use `console.log()` statements in your script and try the connection again. The output of `console.log()` will print to the Real-time Webtask Logs window.
+
diff --git a/articles/connections/database/custom-db/index.md b/articles/connections/database/custom-db/index.md
new file mode 100644
index 0000000000..f3b9a7e57e
--- /dev/null
+++ b/articles/connections/database/custom-db/index.md
@@ -0,0 +1,41 @@
+---
+title: Custom Database Connections
+description: Learn about authenticating users using your database as an identity provider.
+classes: topic-page
+topics:
+ - connections
+ - custom-database
+ - scripts
+contentType:
+ - concept
+ - index
+useCase:
+ - customize-connections
+---
+
+
+
+
Custom Database Connections
+
+ Use a custom database connection when you want to provide Auth0 with access to your own independent (legacy) identity data store primarily for authenticaton (filling the role of an identity provider) and for migrating user data to Auth0's data store.
+
+
+
+Auth0 [Extensibility](/topics/extensibility) allows you to add custom logic to build out last mile solutions for Identity and Access Management (IdAM). Auth0 extensibility comes in several forms: [Rules](/rules), [Hooks](/hooks), and [scripts](/connections/database/custom-db/templates) for both custom database connections and custom database migration. Each is implemented using [Node.js](https://nodejs.org/en/) running on the Auth0 platform in an Auth0 tenant.
+
+Auth0 extensibility executes at different points in the IdAM pipeline:
+
+* **Rules** run when artifacts for user authenticity are generated (i.e., an ID Token in OpenID Connect (OIDC)), an Access Token in OAuth 2.0, or an assertion in Security Assertion Markup Language (SAML).
+* **Hooks** provide additional extensibility for when there is an exchange of non-user related artifacts, and for when user identities are created. See [pre-user registration](/hooks/extensibility-points/pre-user-registration) and [post-user registration](/hooks/extensibility-points/post-user-registration) Hooks for details.
+* **Custom database action scripts** can be used to integrate with an existing user identity store, or can be used where [automatic user migration](/users/concepts/overview-user-migration#automatic-migrations) from an legacy identity store is required.
+
+Whatever the use case, Auth0 extensibility allows you to tailor IdAM operations to your exact requirements. However, if not used in the right way, this can open up the potential for improper or unintended use which can lead to problematic situations down the line. In an attempt to address matters ahead of time, Auth0 provides [best practice guidance](/best-practices/custom-db-connections) to both designers and implementers, and we recommend reading it in its entirety at least once, even if you've already started your journey with Auth0.
+
+<%= include('./_includes/_panel-feature-availability') %>
+
+<%= include('../../../_includes/_topic-links', { links: [
+ 'connections/database/custom-db/overview-custom-db-connections',
+ 'connections/database/custom-db/create-db-connection',
+ 'connections/database/custom-db/templates',
+ 'connections/database/custom-db/error-handling'
+] }) %>
diff --git a/articles/connections/database/custom-db/overview-custom-db-connections.md b/articles/connections/database/custom-db/overview-custom-db-connections.md
new file mode 100644
index 0000000000..d188cffbc1
--- /dev/null
+++ b/articles/connections/database/custom-db/overview-custom-db-connections.md
@@ -0,0 +1,141 @@
+---
+title: Authenticate with Your Own User Store
+description: Learn about authenticating users using your database as an identity provider.
+toc: true
+topics:
+ - connections
+ - custom-database
+ - scripts
+contentType: concept
+useCase:
+ - custom-db-connections
+ - legacy-authentication
+---
+# Authenticate with Your Own User Store
+
+<%= include('./_includes/_panel-feature-availability') %>
+
+<%= include('../../../_includes/_webtask') %>
+
+Use a custom database connection when you want to provide access to your own independent (legacy) identity data store for the following purposes:
+
+* **Authentication**: Use your database as an identity provider in Auth0 to authenticate users. (Referred to as *legacy authentication*.)
+* **Import Users**: Use automatic migration (*trickle* or *lazy* migration)
+* **Proxy access to an Auth0 tenant**: Use Auth0 multi-tenant architecture.
+
+You can create and configure a custom database connection by doing one of the following tasks:
+
+1. Use the [Create connections](/api/management/v2#!/Connections/post_connections) Management API endpoint with the `auth0` strategy.
+
+2. Navigate to [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database), create the connection, and enable the **Use my own database** option to allow database action script editing.
+
+
+
+## How it works
+
+As shown in the diagram below, you use custom database connections as part of Universal Login workflow in order to obtain user identity information from your own, legacy identity store.
+
+
+
+In addition to artifacts common for all [database connection](/connections/database) types, a custom database connection allows you to configure action scripts: custom code that’s used when interfacing with your legacy identity store. Auth0 provides [custom database action script templates](/connections/database/custom-db/templates) for configuration, and the ones you use will depend on whether you are creating a custom database connection for legacy authentication or for automatic migration.
+
+::: panel Best practice
+Action scripts can be implemented as anonymous functions, however anonymous functions make it hard in debugging situations when it comes to interpreting the call-stack generated as a result of any exceptional error condition. For convenience, we recommend providing a function name for each action script.
+:::
+
+### Legacy authentication scenario
+
+In a legacy authentication scenario, a new user record is created within Auth0 during the user's first login, but Auth0 does not store a hash of the user's password. Auth0 will always use the legacy identity store and the identity it contains when authenticating the user.
+
+::: note
+Custom database connections are also used outside of Universal Login workflow. For example, a connection's `changePassword` action script is called when a password change operation occurs for a user that resides in a legacy identity store.
+:::
+
+### Automatic migration scenario
+
+During automatic or trickle migration, Auth0 creates a new user in an identity store (database) managed by Auth0. From then on, Auth0 always uses the identity in the Auth0 managed identity store for authenticating the user. For this to occur, first Auth0 requires the user be authenticated against the legacy identity store and only if this succeeds will the new user be created. The new user will be created using the same id and password that was supplied during authentication.
+
+::: panel Best practice
+Creation of a user in an automatic migration scenario typically occurs after the `login` action script completes. We therefore recommend that you do not attempt any deletion of a user from a legacy identity store as an inline operation (i.e., within the `login` script) but perform the deletion as an independent process. This will prevent accidental deletion of a user should an error condition occur during the migration process.
+:::
+
+In an automatic migration scenario, users remain in the legacy identity store and can be deleted or archived if required. One side effect of this can occur if a user is deleted from Auth0 but still remains present in the legacy identity store. In this case, a login actioned by the deleted user could result in either the `login` and/or `getUser` script being executed and the user being migrated from the legacy identity store once again.
+
+::: panel Best practice
+We recommend marking any legacy user identity as having been migrated before either `login` or `getUser` completes and prior to any eventual legacy store deletion.
+:::
+
+## Size
+
+The total size of implementation for any action script should not exceed 100 kB. The larger the size the more latency is introduced due to the packaging and transport process employed by the Auth0 serverless Webtask platform, and this will have an impact on the performance of your system.
+
+::: note
+The 100 kB limit does not include any `npm` modules that may be referenced as part of any require statements.
+:::
+
+## Environment
+
+Action scripts execute as a series of called JavaScript functions in an instance of a serverless Webtask container. As part of this, a specific environment is provided, together with a number of artefacts supplied by both the Webtask container and the Auth0 authentication server (your Auth0 tenant) itself.
+
+### `npm` modules
+
+Auth0 serverless Webtask containers can make use of a [wide range of `npm` modules](https://auth0-extensions.github.io/canirequire/); `npm` modules not only reduce the overall size of action script code implementation, but also provide access to a wide range of pre-built functionality.
+
+Many publicly available `npm` modules are supported out-of-the-box. The list has been compiled and vetted for any potential security concerns. If you require an `npm` module that is not supported out-of-the-box, then you can make a request in the [Auth0 support portal](https://support.auth0.com/) or to your Auth0 representative. Auth0 will evaluate your request to determine suitability. There is currently no support in Auth0 for the user of `npm` modules from private repositories.
+
+### Variables
+
+Auth0 action scripts support environment variables, accessed via what is known as the globally available [`configuration` object](/connections/database/custom-db/create-db-connection#add-configuration-parameters).
+
+::: panel Best practice
+The `configuration` object should be treated as read-only, and should be used for storing sensitive information such as credentials or API keys for accessing external identity stores. This mitigates having security sensitive values hard coded in an action script.
+:::
+
+The configuration object can also be used to support whatever [Software Development Life Cycle (SDLC)](/dev-lifecycle/setting-up-env) strategies you employ by allowing you to define variables that have tenant specific values. This mitigates hard coded values in an action script which may change depending upon which tenant is executing it.
+
+### `global` object
+
+Auth0 serverless Webtask containers are provisioned from a pool that's associated with each Auth0 tenant. Each container instance makes available the `global` object, which can be accessed across all action scripts that execute within the container instance. The `global` object acts as a global variable that’s unique to the container, and that can be used to define information or functions used across all action scripts that run in the container instance.
+
+This means that the `global` object can be used to cache expensive resources as long as those resources are not user-specific. For example, you could use it to store an Access Token for a third-party (e.g., logging) API that provides non-user-specific functionality. Or, you can store an Access Token to your own non-user-specific API defined in Auth0 and obtained via the [Client Credentials](/flows/concepts/client-credentials) flow.
+
+::: warning
+An action script may execute in any of the container instances already running, or in a newly created container instance (which may subsequently be added to the pool). There is no container affinity for action script execution in Auth0. This means that you should avoid storing any user-specific information in the `global` object, and should always ensure that any declaration made within the `global` object provides for initialization too.
+:::
+
+Each time a Webtask container is recycled, or for each instantiation of a new Webtask container, the `global` object it defines is reset. Thus, any declaration of assignment within the `global` object associated with a container should also include provision for initialization too.
+
+::: panel Best practice
+To provide performance flexibility, serverless Webtask containers are provisioned in Auth0 on an ad-hoc basis and are also subject to various recycle policies. In general, we recommend that you do not consider the life of a `global` object to be anything more than 20 minutes.
+:::
+
+## Security
+
+### Access legacy identity storage via custom API
+
+Protecting legacy identity storage from general access is a recommended best practice. Exposing a database directly to the internet, for example, can be extremely problematic: database interfaces for SQL and the like are extremely open in terms of functionality, which violates the principle of least privilege when it comes to security.
+
+::: panel Best practice
+We recommend that you implement an API to provide least privilege to your legacy identity store (database), rather than simply opening up general access via the internet.
+:::
+
+The alternative is to create a simple (custom) API, protected via use of an access token, that each action script can call. This would act as the interface to the legacy identity store. Client credentials grant flow can then be used to obtain an access token from within a script, and this can subsequently be cached for reuse in the `global` object in order to improve performance. The API can then provide a discrete number of protected endpoints that perform only the legacy management functionality required (e.g., `read user`, `change password`, etc.)
+
+::: panel Best practice
+By default, Auth0 will give you a token for any API if you authenticate successfully and include the appropriate audience. Restricting access to the legacy identity store API by restricting access token allocation via use of a Rule, will prevent unauthorized usage and mitigate a number of attack vector scenarios, such as where redirect to `/authorize` is intercepted and the audience to the API is added.
+:::
+
+### Allowlist access to legacy identity storage
+
+Whether managing access to a legacy identity store via custom API, or using the native interface provided, restricting access to the list of IP addresses associated with your Auth0 tenant. Allowlisting constrains access to the legacy identity store ensuring that only custom database action scripts defined in Auth0 are permitted.
+
+::: warning
+The Auth0 IP address allowlist is shared amongst all Auth0 tenants defined to a region. Never use the allowlist as the sole method of securing access to your legacy identity store; doing so could open up potential security vulnerabilities allowing unauthorized access to your users.
+:::
+
+## Keep reading
+
+* [Create Custom Database Connections](/connections/database/custom-db/create-db-connection)
+* [Custom Database Action Script Templates](/connections/database/custom-db/templates)
+* [Handle Errors and Troubleshoot Your Custom DB Scripts](/connections/database/custom-db/error-handling)
+* [Migrate Your Users to Auth0](/users/concepts/overview-user-migration)
diff --git a/articles/connections/database/custom-db/templates/change-email.md b/articles/connections/database/custom-db/templates/change-email.md
new file mode 100644
index 0000000000..3322d8573a
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/change-email.md
@@ -0,0 +1,46 @@
+---
+description: Custom database action script for changing a user's email.
+toc: true
+topics:
+ - connections
+ - custom-database
+contentType: reference
+useCase:
+ - customize-connections
+---
+# Change Email Script
+
+The **Change Email** script implements the function executed when a change in the email address, or the email address verification status, for a user occurs. We recommend naming this function `changeEmail`. Typically the script is executed when a change in either email address and/or email address verification status is actioned via the Auth0 Dashboard or the Auth0 Management API. The script is only used in a legacy authentication scenario, and must be implemented if support is required for email address/status change via Auth0.
+
+The change email script is not configurable via the Auth0 Dashboard. There are no script templates available. You can use either the Auth0 [Deploy CLI Tool](/extensions/deploy-cli) or the Auth0 [Management API](/api/management/v2#!/Connections) to create or update the change email script.
+
+The changeEmail function should be defined as follows:
+
+```js
+function changeEmail(email, newEmail, verified, callback) {
+ // TODO: implement your script
+ return callback(null);
+}
+```
+
+::: warning
+If you change any aspect of a connection via the Dashboard in Auth0, and that connection makes use of a **Change Email** script, then the script will be deleted.
+:::
+
+| **Parameter** | **Description** |
+| --- | --- |
+| `email` | The email address for the user as the user identifying credential. |
+| `newEmail` | The new email address for the user. |
+| `verified` | The verified state of the new email address, passed as either a true or false value. Email verification status information is typically returned via `email_verified` as part of any user profile information returned (see `login` and `get user` for further details), so email verification state should be preserved in the legacy data store for future reference. |
+| `callback` | Executed with up to two parameters. The first parameter is an indication of status: a `null` first parameter with a corresponding second parameter of `true` indicates that the operation executed successfully; a `null` first parameter with no corresponding second parameter (or one with a value of `false`) indicates that no password change was performed (possibly due to the user not being found). A non `null` first parameter value indicates that some error condition occurred. |
+
+<%= include('../_includes/_bp-error-object') %>
+
+## Keep reading
+
+* [Change Passwords](/connections/database/custom-db/templates/change-password)
+* [Create](/connections/database/custom-db/templates/create)
+* [Delete](/connections/database/custom-db/templates/delete)
+* [Get User](/connections/database/custom-db/templates/get-user)
+* [Login](/connections/database/custom-db/templates/login)
+* [Verify](/connections/database/custom-db/templates/verify)
diff --git a/articles/connections/database/custom-db/templates/change-password.md b/articles/connections/database/custom-db/templates/change-password.md
new file mode 100644
index 0000000000..e39f947fea
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/change-password.md
@@ -0,0 +1,536 @@
+---
+description: Custom database action script templates for changing a user's password.
+toc: true
+topics:
+ - connections
+ - custom-database
+contentType: reference
+useCase:
+ - customize-connections
+---
+# Change Password Script Templates
+
+The **Change Password** script implements the function executed to change the password associated with the user identity in the your legacy identity store. We recommend naming this function `changePassword`. The script is only used in a legacy authentication scenario.
+
+This script executes whenever a user tries to change their password; the user will receive the password reset email, which includes the link they need to follow to change their password. This script is **optional** however, a call to `changePassword` is typically preceded by a call to `getUser`, so if you implement the change password script you will also need to implement the [get user script](/connections/database/custom-db/templates/get-user).
+
+::: panel Best practice
+While it’s not mandatory to implement the `changePassword` function, it is a recommended best practice. The `changePassword` function is required to for the password reset workflow recommended for [great customer experience](https://auth0.com/learn/password-reset/).
+:::
+
+The script is executed whenever [password reset](/universal-login/password-reset) workflow is performed and also during password change workflow via the Auth0 Dashboard or the Auth0 Management API.
+
+The `changePassword` function implemented in the **Change Password** script should be defined as follows:
+
+```js
+function changePassword(email, newPassword, callback) {
+ // TODO: implement your script
+ return callback(null, result);
+}
+```
+
+| **Parameter** | **Description** |
+| --- | --- |
+| `email` | The email address for the user as the user identifying credential. |
+| `password` | The new password credential for the user. The password credential for the user is passed to the script in plain text so care must be taken regarding its use. |
+| `callback` | Executed with up to two parameters. The first parameter is an indication of status: a `null` first parameter with a corresponding second parameter of `true` indicates that the operation executed successfully; a `null` first parameter with no corresponding second parameter (or one with a value of `false`) indicates that no password change was performed (possibly due to the user not being found). A non `null` first parameter value indicates that some error condition occurred. |
+
+<%= include('../_includes/_bp-error-object') %>
+
+<%= include('../_includes/_panel-bcrypt-hash-encryption') %>
+
+## Language-specific script examples
+
+Auth0 provides sample scripts for use with the following languages/technologies:
+
+::: next-steps
+* [JavaScript](/connections/database/custom-db/templates/change-password#javascript)
+* [ASP.NET Membership Provider (MVC3 - Universal Providers)](/connections/database/custom-db/templates/change-password#asp-net-membership-provider-mvc3-universal-providers-)
+* [ASP.NET Membership Provider (MVC4 - Simple Membership)](/connections/database/custom-db/templates/change-password#asp-net-membership-provider-mvc4-simple-membership-)
+* [MongoDB](/connections/database/custom-db/templates/change-password#mongodb)
+* [MySQL](/connections/database/custom-db/templates/change-password#mysql)
+* [PostgreSQL](/connections/database/custom-db/templates/change-password#postgresql)
+* [SQL Server](/connections/database/custom-db/templates/change-password#sql-server)
+* [Windows Azure SQL Database](/connections/database/custom-db/templates/change-password#windows-azure-sql-database)
+* [Request with Basic Auth](/connections/database/custom-db/templates/change-password#request-with-basic-auth)
+:::
+
+### JavaScript
+
+```
+function changePassword(email, newPassword, callback) {
+ // This script should change the password stored for the current user in your
+ // database. It is executed when the user clicks on the confirmation link
+ // after a reset password request.
+ // The content and behavior of password confirmation emails can be customized
+ // here: https://manage.auth0.com/#/emails
+ // The `newPassword` parameter of this function is in plain text. It must be
+ // hashed/salted to match whatever is stored in your database.
+ //
+ // There are three ways that this script can finish:
+ // 1. The user's password was updated successfully:
+ // callback(null, true);
+ // 2. The user's password was not updated:
+ // callback(null, false);
+ // 3. Something went wrong while trying to reach your database:
+ // callback(new Error("my error message"));
+ //
+ // If an error is returned, it will be passed to the query string of the page
+ // to which the user is being redirected after clicking the confirmation link.
+ // For example, returning `callback(new Error("error"))` and redirecting to
+ // https://example.com would redirect to the following URL:
+ // https://example.com?email=alice%40example.com&message=error&success=false
+
+ const msg = 'Please implement the Change Password script for this database ' +
+ 'connection at https://manage.auth0.com/#/connections/database';
+ return callback(new Error(msg));
+}
+```
+
+### ASP.NET Membership Provider (MVC3 - Universal Providers)
+
+```
+function changePassword(email, newPassword, callback) {
+
+ var crypto = require('crypto');
+ var Connection = require('tedious').Connection;
+ var Request = require('tedious').Request;
+ var TYPES = require('tedious').TYPES
+
+ var connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ // encrypt: true for Windows Azure enable this
+ }
+ });
+
+ /**
+ * hashPassword
+ *
+ * This function creates a hashed version of the password to store in the database.
+ *
+ * @password {[string]} the password entered by the user
+ * @return {[string]} the hashed password
+ */
+ function hashPassword(password, salt) {
+ // the default implementation uses HMACSHA256 and since Key length is 64
+ // and default salt is 16 bytes, Membership will fill the buffer repeating the salt
+ var key = Buffer.concat([salt, salt, salt, salt]);
+ var hmac = crypto.createHmac('sha256', key);
+ hmac.update(Buffer.from(password, 'ucs2'));
+ var hashed = hmac.digest('base64');
+
+ return hashed;
+ }
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) {
+ return callback(err);
+ }
+ updateMembershipUser(email, newPassword, function(err, wasUpdated) {
+ if (err) {
+ return callback(err); // this will return a 500
+ }
+
+ callback(null, wasUpdated);
+ });
+ });
+
+ function updateMembershipUser(email, newPassword, callback) {
+ var salt = crypto.randomBytes(16);
+ var hashedPassword = hashPassword(newPassword, salt);
+
+ var updateMembership =
+ 'UPDATE Memberships '+
+ 'SET Password=@NewPassword, PasswordSalt=@NewSalt, LastPasswordChangedDate=GETDATE() '+
+ 'WHERE Email=@Email';
+
+ var updateMembershipQuery = new Request(updateMembership, function (membershipErr, membershipCount) {
+ if (membershipErr) {
+ return callback(membershipErr);
+ }
+ callback(null, membershipCount > 0);
+ });
+
+ updateMembershipQuery.addParameter('NewPassword', TYPES.VarChar, hashedPassword);
+ updateMembershipQuery.addParameter('NewSalt', TYPES.VarChar, salt.toString('base64'));
+ updateMembershipQuery.addParameter('Email', TYPES.VarChar, email);
+
+ connection.execSql(updateMembershipQuery);
+ }
+}
+```
+
+### ASP.NET Membership Provider (MVC4 - Simple Membership)
+
+```
+function changePassword(email, newPassword, callback) {
+
+ var crypto = require('crypto');
+ var Connection = require('tedious').Connection;
+ var Request = require('tedious').Request;
+ var TYPES = require('tedious').TYPES
+
+ var connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ // encrypt: true for Windows Azure enable this
+ }
+ });
+
+ /**
+ * hashPassword
+ *
+ * This function hashes a password using HMAC SHA256 algorithm.
+ *
+ * @password {[string]} password to be hased
+ * @salt {[string]} salt to be used in the hashing process
+ * @callback {[function]} callback to be called after hashing the password
+ */
+ function hashPassword(password, salt, callback) {
+ var iterations = 1000;
+ var passwordHashLength = 32;
+
+ crypto.pbkdf2(password, salt, iterations, passwordHashLength, function (err, hashed) {
+ if (err) {
+ return callback(err);
+ }
+ var result = Buffer.concat([Buffer.from([0], 1), salt, Buffer.from(hashed, 'binary')]);
+
+ var resultBase64 = result.toString('base64');
+
+ callback(null, resultBase64);
+ });
+
+ }
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) {
+ return callback(err);
+ }
+ updateMembershipUser(email, newPassword, function(err, wasUpdated) {
+ if (err) {
+ return callback(err); // this will return a 500
+ }
+
+ callback(null, wasUpdated);
+ });
+ });
+
+ function findUserId(email, callback) {
+ var findUserIdFromEmail =
+ 'SELECT UserProfile.UserId FROM ' +
+ 'UserProfile INNER JOIN webpages_Membership ' +
+ 'ON UserProfile.UserId = webpages_Membership.UserId ' +
+ 'WHERE UserName = @Email';
+
+ var findUserIdFromEmailQuery = new Request(findUserIdFromEmail, function (err, rowCount, rows) {
+ if (err) {
+ return callback(err);
+ }
+
+ // No record found with that email
+ if (rowCount < 1) {
+ return callback(null, null);
+ }
+
+ var userId = rows[0][0].value;
+
+ callback(null, userId);
+
+ });
+
+ findUserIdFromEmailQuery.addParameter('Email', TYPES.VarChar, email);
+
+ connection.execSql(findUserIdFromEmailQuery);
+ }
+
+ function updateMembershipUser(email, newPassword, callback) {
+ findUserId(email, function (err, userId) {
+ if (err) {
+ return callback(err);
+ }
+
+ if (userId === null) {
+ return callback();
+ }
+
+ var salt = crypto.randomBytes(16);
+
+ var updateMembership =
+ 'UPDATE webpages_Membership '+
+ 'SET Password=@NewPassword, PasswordChangedDate=GETDATE() '+
+ 'WHERE UserId=@UserId';
+
+ var updateMembershipQuery = new Request(updateMembership, function (err, rowCount) {
+ if (err) {
+ return callback(err);
+ }
+
+ if (rowCount < 1) {
+ return callback();
+ }
+
+ callback(null, rowCount > 0);
+ });
+
+ hashPassword(newPassword, salt, function (err, hashedPassword) {
+ if (err) {
+ return callback(err);
+ }
+
+ updateMembershipQuery.addParameter('NewPassword', TYPES.VarChar, hashedPassword);
+ updateMembershipQuery.addParameter('UserId', TYPES.VarChar, userId);
+
+ connection.execSql(updateMembershipQuery);
+ });
+ });
+ }
+}
+```
+
+### MongoDB
+
+```
+function changePassword(email, newPassword, callback) {
+ const bcrypt = require('bcrypt');
+ const MongoClient = require('mongodb@3.1.4').MongoClient;
+ const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
+
+ client.connect(function (err) {
+ if (err) return callback(err);
+
+ const db = client.db('db-name');
+ const users = db.collection('users');
+
+ bcrypt.hash(newPassword, 10, function (err, hash) {
+ if (err) {
+ client.close();
+ return callback(err);
+ }
+
+ users.update({ email: email }, { $set: { password: hash } }, function (err, count) {
+ client.close();
+ if (err) return callback(err);
+ callback(null, count > 0);
+ });
+ });
+ });
+}
+```
+
+### MySQL
+
+```
+function changePassword(email, newPassword, callback) {
+ const mysql = require('mysql');
+ const bcrypt = require('bcrypt');
+
+ const connection = mysql({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret',
+ database: 'mydb'
+ });
+
+ connection.connect();
+
+ const query = 'UPDATE users SET password = ? WHERE email = ?';
+
+ bcrypt.hash(newPassword, 10, function(err, hash) {
+ if (err) return callback(err);
+
+ connection.query(query, [ hash, email ], function(err, results) {
+ if (err) return callback(err);
+ callback(null, results.length > 0);
+ });
+ });
+}
+```
+
+### PostgreSQL
+
+```
+function changePassword (email, newPassword, callback) {
+ //this example uses the "pg" library
+ //more info here: https://github.com/brianc/node-postgres
+
+ const bcrypt = require('bcrypt');
+ const postgres = require('pg');
+
+ const conString = 'postgres://user:pass@localhost/mydb';
+ postgres.connect(conString, function (err, client, done) {
+ if (err) return callback(err);
+
+ bcrypt.hash(newPassword, 10, function (err, hash) {
+ if (err) return callback(err);
+
+ const query = 'UPDATE users SET password = $1 WHERE email = $2';
+ client.query(query, [hash, email], function (err, result) {
+ // NOTE: always call `done()` here to close
+ // the connection to the database
+ done();
+
+ return callback(err, result && result.rowCount > 0);
+ });
+ });
+ });
+}
+```
+
+### SQL Server
+
+```
+function changePassword (email, newPassword, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://tediousjs.github.io/tedious/
+ const bcrypt = require('bcrypt');
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'test',
+ password: 'test',
+ server: 'localhost',
+ options: {
+ database: 'mydb'
+ }
+ });
+
+ const query = 'UPDATE dbo.Users SET Password = @NewPassword WHERE Email = @Email';
+
+ connection.on('debug', function(text) {
+ console.log(text);
+ }).on('errorMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+
+ const request = new Request(query, function (err, rows) {
+ if (err) return callback(err);
+ callback(null, rows > 0);
+ });
+
+ bcrypt.hash(newPassword, 10, function (err, hash) {
+ if (err) return callback(err);
+ request.addParameter('NewPassword', TYPES.VarChar, hash);
+ request.addParameter('Email', TYPES.VarChar, email);
+ connection.execSql(request);
+ });
+ });
+}
+```
+
+### Windows Azure SQL Database
+
+```
+function changePassword (email, newPassword, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+
+ var Connection = require('tedious@1.11.0').Connection;
+ var Request = require('tedious@1.11.0').Request;
+ var TYPES = require('tedious@1.11.0').TYPES;
+ var bcrypt = require('bcrypt');
+
+ var connection = new Connection({
+ userName: 'your-user@your-server-id.database.windows.net',
+ password: 'the-password',
+ server: 'your-server-id.database.windows.net',
+ options: {
+ database: 'mydb',
+ encrypt: true
+ }
+ });
+
+ var query = 'UPDATE dbo.Users SET Password = @NewPassword ' +
+ 'WHERE Email = @Email';
+
+ connection.on('debug', function(text) {
+ // Uncomment next line in order to enable debugging messages
+ // console.log(text);
+ }).on('errorMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function(text) {
+ // Uncomment next line in order to enable information messages
+ // console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) { return callback(err); }
+
+ var request = new Request(query, function (err, rows) {
+ if (err) { return callback(err); }
+ console.log('rows: ' + rows);
+ callback(null, rows > 0);
+ });
+
+ bcrypt.hash(newPassword, 10, function (err, hash) {
+ if (err) { return callback(err); }
+ request.addParameter('NewPassword', TYPES.VarChar, hash);
+ request.addParameter('Email', TYPES.VarChar, email);
+ connection.execSql(request);
+ });
+ });
+}
+```
+
+### Request with Basic Auth
+
+```
+function changePassword (email, newPassword, callback) {
+
+ var request = require('request');
+
+ request.put({
+ url: 'https://myserviceurl.com/users',
+ json: { email: email, password: newPassword }
+ //for more options check:
+ //https://github.com/mikeal/request#requestoptions-callback
+ }, function (err, response, body) {
+
+ if (err) return callback(err);
+ if (response.statusCode === 401) return callback();
+ callback(null, body);
+ });
+
+}
+```
+
+## Keep reading
+
+* [Create](/connections/database/custom-db/templates/create)
+* [Delete](/connections/database/custom-db/templates/delete)
+* [Get User](/connections/database/custom-db/templates/get-user)
+* [Login](/connections/database/custom-db/templates/login)
+* [Verify](/connections/database/custom-db/templates/verify)
+* [Change Email](/connections/database/custom-db/templates/change-email)
diff --git a/articles/connections/database/custom-db/templates/create.md b/articles/connections/database/custom-db/templates/create.md
new file mode 100644
index 0000000000..8f8e287a03
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/create.md
@@ -0,0 +1,594 @@
+---
+description: Custom database action script templates for user creation.
+toc: true
+topics:
+ - connections
+ - custom-database
+ - create-users
+contentType: reference
+useCase:
+ - customize-connections
+---
+# Create Script Templates
+
+The **Create** script implements the function executed to create a user in your database. We recommend naming this function `create`. Use this script if you want new users to sign up via Auth0 so that Auth0 creates the users in your legacy data store. Not using the script doesn't prevent the creation of users by a mechanism external to Auth0.
+
+This script executes when a user signs up or when an administrator creates the user via the Auth0 Dashboard or Management API. When creating users, Auth0 calls the **Get User** script before the **Create** script. Be sure to implement both database action scripts if you are creating new users. When the script finishes execution, the **Login** script runs to verify that the user was created successfully.
+
+The `create` function implemented in the script should be defined as follows:
+
+```js
+function create(user, callback) {
+ // TODO: implement your script
+ return callback(null);
+}
+```
+
+| **Parameter** | **Description** |
+| --- | --- |
+| `user` | An object containing attributes associated with the user identity to be created. |
+| `callback` | Executed with a single parameter. The parameter is an indication of status: a `null` indicates that the operation executed successfully, while a non `null` value indicates that some error condition occurred. |
+
+<%= include('../_includes/_bp-error-object') %>
+
+<%= include('../_includes/_panel-bcrypt-hash-encryption') %>
+
+## `user` object example
+
+```js
+{
+ client_id: "",
+ tenant: "",
+ email: "",
+ password: "",
+ username: "",
+ user_metadata: {
+ "language": "en"
+ },
+ app_metadata: {
+ "plan": "full"
+ }
+}
+```
+
+The `user` object can contain the following properties:
+
+| **Property** | **Description** |
+| - | - |
+| `client_id` | the client ID of the application for which the user signed up, or the API key if the user was created through the Auth0 Dashboard or Management API |
+| `tenant` | the name of the Auth0 account |
+| `email` | the user's email |
+| `password` | the password entered by the user (in plain text) |
+| `username` | required only if the custom database connection has [`Requires Username`](/connections/database/require-username) enabled
+| `connection` | the name of the database connection |
+| `user_metadata` | optional |
+| `app_metadata` | optional |
+
+::: panel Best practice
+If the custom database connection has [`Requires Username`](/connections/database/require-username) enabled, then `username` also needs to be used by any subsequent `login` or `getUser` execution, so you should store it in the legacy identity store.
+:::
+
+While `user_metadata` and `app_metadata` are optional, if supplied, they do not need to be stored in the legacy identity store; Auth0 automatically stores these values as part of the [user profile](/users/concepts/overview-user-profile) record created internally. These values are (optionally) provided as a reference: their contents potentially being influential to legacy identity creation.
+
+::: note
+Unlike with `login`, `app_metadata` is specified as-is and will not be renamed as `metadata`.
+:::
+
+Finally, if you [create and use custom fields](/libraries/custom-signup#using-the-api) during the registration process, these properties are included in the `user` object as well.
+
+## Script execution results
+
+There are three ways a **Create** script can finish:
+
+| **Result** | **Description** |
+| - | - |
+| `callback(null);` | A user was successfully created |
+| `callback(new ValidationError("user_exists", "my error message"));` | This user already exists in your database |
+| `callback(new Error("my error message"));` | Something went wrong while trying to reach your database |
+
+## Language-specific script examples
+
+Auth0 provides sample scripts for use with the following languages/technologies:
+
+::: next-steps
+* [JavaScript](/connections/database/custom-db/templates/create#javascript)
+* [ASP.NET Membership Provider (MVC3 - Universal Providers)](/connections/database/custom-db/templates/create#asp-net-membership-provider-mvc3-universal-providers-)
+* [ASP.NET Membership Provider (MVC4 - Simple Membership)](/connections/database/custom-db/templates/create#asp-net-membership-provider-mvc4-simple-membership-)
+* [MongoDB](/connections/database/custom-db/templates/create#mongodb)
+* [MySQL](/connections/database/custom-db/templates/create#mysql)
+* [PostgreSQL](/connections/database/custom-db/templates/create#postgresql)
+* [SQL Server](/connections/database/custom-db/templates/create#sql-server)
+* [Windows Azure SQL Database](/connections/database/custom-db/templates/create#windows-azure-sql-database)
+* [Request with Basic Auth](/connections/database/custom-db/templates/create#request-with-basic-auth)
+:::
+
+### JavaScript
+
+```
+function create(user, callback) {
+ // This script should create a user entry in your existing database. It will
+ // be executed when a user attempts to sign up, or when a user is created
+ // through the Auth0 Dashboard or Management API.
+ // When this script has finished executing, the Login script will be
+ // executed immediately afterwards, to verify that the user was created
+ // successfully.
+ //
+ // The user object will always contain the following properties:
+ // * email: the user's email
+ // * password: the password entered by the user, in plain text
+ // * tenant: the name of this Auth0 account
+ // * client_id: the client ID of the application where the user signed up, or
+ // API key if created through the Management API or Auth0 Dashboard
+ // * connection: the name of this database connection
+ //
+ // There are three ways this script can finish:
+ // 1. A user was successfully created
+ // callback(null);
+ // 2. This user already exists in your database
+ // callback(new ValidationError("user_exists", "my error message"));
+ // 3. Something went wrong while trying to reach your database
+ // callback(new Error("my error message"));
+
+ const msg = 'Please implement the Create script for this database connection ' +
+ 'at https://manage.auth0.com/#/connections/database';
+ return callback(new Error(msg));
+}
+```
+
+### ASP.NET Membership Provider (MVC3 - Universal Providers)
+
+```
+function create(user, callback) {
+ const crypto = require('crypto');
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true,
+ // Required to retrieve userId needed for Membership entity creation
+ rowCollectionOnRequestCompletion: true
+ }
+ });
+
+ const applicationId = 'your-application-id-goes-here';
+
+ /**
+ * hashPassword
+ *
+ * This function creates a hashed version of the password to store in the database.
+ *
+ * @password {[string]} the password entered by the user
+ * @return {[string]} the hashed password
+ */
+ function hashPassword(password, salt) {
+ // the default implementation uses HMACSHA256 and since Key length is 64
+ // and default salt is 16 bytes, Membership will fill the buffer repeating the salt
+ const key = Buffer.concat([salt, salt, salt, salt]);
+ const hmac = crypto.createHmac('sha256', key);
+ hmac.update(Buffer.from(password, 'ucs2'));
+
+ return hmac.digest('base64');
+ }
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ // console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function(err) {
+ if (err) {
+ return callback(err);
+ }
+ createMembershipUser(user, function(err, user) {
+ if (err) return callback(err); // this will return a 500
+ if (!user) return callback(); // this will return a 401
+
+ callback(null, user);
+ });
+ });
+
+ function createMembershipUser(user, callback) {
+ const userData = {
+ UserName: user.email,
+ ApplicationId: applicationId
+ };
+ const createUser =
+ 'INSERT INTO Users (UserName, LastActivityDate, ApplicationId, UserId, IsAnonymous) ' +
+ 'OUTPUT Inserted.UserId ' +
+ 'VALUES (@UserName, GETDATE(), @ApplicationId, NEWID(), \'false\')';
+
+ const createUserQuery = new Request(createUser, function(err, rowCount, rows) {
+ if (err) return callback(err);
+
+ // No records added
+ if (rowCount === 0) return callback(null);
+
+ const userId = rows[0][0].value;
+ const salt = crypto.randomBytes(16);
+ const membershipData = {
+ ApplicationId: applicationId,
+ Email: user.email,
+ Password: hashPassword(user.password, salt),
+ PasswordSalt: salt.toString('base64'),
+ UserId: userId
+ };
+
+ const createMembership =
+ 'INSERT INTO Memberships (ApplicationId, UserId, Password, PasswordFormat, ' +
+ 'PasswordSalt, Email, isApproved, isLockedOut, CreateDate, LastLoginDate, ' +
+ 'LastPasswordChangedDate, LastLockoutDate, FailedPasswordAttemptCount, ' +
+ 'FailedPasswordAttemptWindowStart, FailedPasswordAnswerAttemptCount, ' +
+ 'FailedPasswordAnswerAttemptWindowsStart) ' +
+ 'VALUES ' +
+ '(@ApplicationId, @UserId, @Password, 1, @PasswordSalt, ' +
+ '@Email, \'false\', \'false\', GETDATE(), GETDATE(), GETDATE(), GETDATE(), 0, 0, 0, 0)';
+
+ const createMembershipQuery = new Request(createMembership, function(err, rowCount) {
+ if (err) return callback(err);
+
+ if (rowCount === 0) return callback(null);
+
+ callback(null, rowCount > 0);
+ });
+
+ createMembershipQuery.addParameter('ApplicationId', TYPES.VarChar, membershipData.ApplicationId);
+ createMembershipQuery.addParameter('Email', TYPES.VarChar, membershipData.Email);
+ createMembershipQuery.addParameter('Password', TYPES.VarChar, membershipData.Password);
+ createMembershipQuery.addParameter('PasswordSalt', TYPES.VarChar, membershipData.PasswordSalt);
+ createMembershipQuery.addParameter('UserId', TYPES.VarChar, membershipData.UserId);
+
+ connection.execSql(createMembershipQuery);
+ });
+
+ createUserQuery.addParameter('UserName', TYPES.VarChar, userData.UserName);
+ createUserQuery.addParameter('ApplicationId', TYPES.VarChar, userData.ApplicationId);
+
+ connection.execSql(createUserQuery);
+ }
+}
+```
+
+### ASP.NET Membership Provider (MVC4 - Simple Membership)
+
+```
+function create(user, callback) {
+ const crypto = require('crypto');
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true,
+ // Required to retrieve userId needed for Membership entity creation
+ rowCollectionOnRequestCompletion: true
+ }
+ });
+
+ /**
+ * hashPassword
+ *
+ * This function hashes a password using HMAC SHA256 algorithm.
+ *
+ * @password {[string]} password to be hased
+ * @salt {[string]} salt to be used in the hashing process
+ * @callback {[function]} callback to be called after hashing the password
+ */
+ function hashPassword(password, salt, callback) {
+ const iterations = 1000;
+ const passwordHashLength = 32;
+
+ crypto.pbkdf2(password, salt, iterations, passwordHashLength, 'sha1', function (err, hashed) {
+ if (err) return callback(err);
+
+ const result = Buffer.concat([Buffer.from([0], 1), salt, Buffer.from(hashed, 'binary')]);
+ const resultBase64 = result.toString('base64');
+
+ callback(null, resultBase64);
+ });
+ }
+
+ connection.on('debug', function (text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ // console.log(text);
+ }).on('errorMessage', function (text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+
+ const createUser =
+ 'INSERT INTO UserProfile (UserName) ' +
+ 'OUTPUT Inserted.UserId ' +
+ 'VALUES (@UserName)';
+
+ const createUserQuery = new Request(createUser, function (err, rowCount, rows) {
+ if (err || rowCount === 0) return callback(err);
+
+ const userId = rows[0][0].value;
+ const salt = crypto.randomBytes(16);
+
+ const createMembership =
+ 'INSERT INTO webpages_Membership ' +
+ '(UserId, CreateDate, IsConfirmed, PasswordFailuresSinceLastSuccess, Password, PasswordSalt) ' +
+ 'VALUES ' +
+ '(@UserId, GETDATE(), \'false\', 0, @Password, \'\')';
+
+ const createMembershipQuery = new Request(createMembership, function (err, rowCount) {
+ if (err || rowCount === 0) return callback(err);
+
+ callback(null, rowCount > 0);
+ });
+
+ hashPassword(user.password, salt, function (err, hashedPassword) {
+ if (err) return callback(err);
+ createMembershipQuery.addParameter('Password', TYPES.VarChar, hashedPassword);
+ createMembershipQuery.addParameter('PasswordSalt', TYPES.VarChar, salt.toString('base64'));
+ createMembershipQuery.addParameter('UserId', TYPES.VarChar, userId);
+
+ connection.execSql(createMembershipQuery);
+ });
+ });
+
+ createUserQuery.addParameter('UserName', TYPES.VarChar, user.email);
+
+ connection.execSql(createUserQuery);
+ });
+}
+```
+
+### MongoDB
+
+```
+function create(user, callback) {
+ const bcrypt = require('bcrypt');
+ const MongoClient = require('mongodb@3.1.4').MongoClient;
+ const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
+
+ client.connect(function (err) {
+ if (err) return callback(err);
+
+ const db = client.db('db-name');
+ const users = db.collection('users');
+
+ users.findOne({ email: user.email }, function (err, withSameMail) {
+ if (err || withSameMail) {
+ client.close();
+ return callback(err || new Error('the user already exists'));
+ }
+
+ bcrypt.hash(user.password, 10, function (err, hash) {
+ if (err) {
+ client.close();
+ return callback(err);
+ }
+
+ user.password = hash;
+ users.insert(user, function (err, inserted) {
+ client.close();
+
+ if (err) return callback(err);
+ callback(null);
+ });
+ });
+ });
+ });
+}
+```
+
+### MySQL
+
+```
+function create(user, callback) {
+ const mysql = require('mysql');
+ const bcrypt = require('bcrypt');
+
+ const connection = mysql({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret',
+ database: 'mydb'
+ });
+
+ connection.connect();
+
+ const query = 'INSERT INTO users SET ?';
+
+ bcrypt.hash(user.password, 10, function(err, hash) {
+ if (err) return callback(err);
+
+ const insert = {
+ password: hash,
+ email: user.email
+ };
+
+ connection.query(query, insert, function(err, results) {
+ if (err) return callback(err);
+ if (results.length === 0) return callback();
+ callback(null);
+ });
+ });
+}
+```
+
+### PostgreSQL
+
+```
+function create(user, callback) {
+ //this example uses the "pg" library
+ //more info here: https://github.com/brianc/node-postgres
+
+ const bcrypt = require('bcrypt');
+ const postgres = require('pg');
+
+ const conString = 'postgres://user:pass@localhost/mydb';
+ postgres.connect(conString, function (err, client, done) {
+ if (err) return callback(err);
+
+ bcrypt.hash(user.password, 10, function (err, hashedPassword) {
+ if (err) return callback(err);
+
+ const query = 'INSERT INTO users(email, password) VALUES ($1, $2)';
+ client.query(query, [user.email, hashedPassword], function (err, result) {
+ // NOTE: always call `done()` here to close
+ // the connection to the database
+ done();
+
+ return callback(err);
+ });
+ });
+ });
+}
+```
+
+### SQL Server
+
+```
+
+function create(user, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+ const bcrypt = require('bcrypt');
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'test',
+ password: 'test',
+ server: 'localhost',
+ options: {
+ database: 'mydb'
+ }
+ });
+
+ const query = 'INSERT INTO dbo.Users SET Email = @Email, Password = @Password';
+
+ connection.on('debug', function(text) {
+ console.log(text);
+ }).on('errorMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+
+ const request = new Request(query, function (err, rows) {
+ if (err) return callback(err);
+ callback(null);
+ });
+
+ bcrypt.hash(user.password, 10, function(err, hash) {
+ if (err) return callback(err);
+ request.addParameter('Email', TYPES.VarChar, user.email);
+ request.addParameter('Password', TYPES.VarChar, hash);
+ connection.execSql(request);
+ });
+ });
+}
+```
+
+### Windows Azure SQL Database
+
+```
+function create (user, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+
+ var Connection = require('tedious@1.11.0').Connection;
+ var Request = require('tedious@1.11.0').Request;
+ var TYPES = require('tedious@1.11.0').TYPES;
+ var bcrypt = require('bcrypt');
+
+ var connection = new Connection({
+ userName: 'your-user@your-server-id.database.windows.net',
+ password: 'the-password',
+ server: 'your-server-id.database.windows.net',
+ options: {
+ database: 'mydb',
+ encrypt: true
+ }
+ });
+
+ var query = "INSERT INTO users (Email, Password) VALUES (@Email, @Password)";
+
+ connection.on('debug', function(text) {
+ // Uncomment next line in order to enable debugging messages
+ // console.log(text);
+ }).on('errorMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function(text) {
+ // Uncomment next line in order to enable information messages
+ // console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) { return callback(err); }
+
+ var request = new Request(query, function (err, rows) {
+ if (err) { return callback(err); }
+ console.log('rows: ' + rows);
+ callback(null);
+ });
+
+ bcrypt.hash(user.password, 10, function (err, hashedPassword) {
+ if (err) { return callback(err); }
+ request.addParameter('Email', TYPES.VarChar, user.email);
+ request.addParameter('Password', TYPES.VarChar, hashedPassword);
+ connection.execSql(request);
+ });
+
+ });
+}
+```
+
+### Request with Basic Auth
+
+```
+function create(user, callback) {
+ const request = require('request');
+
+ request.post({
+ url: 'https://myserviceurl.com/users',
+ json: user
+ //for more options check:
+ //https://github.com/mikeal/request#requestoptions-callback
+ }, function(err, response, body) {
+ if (err) return callback(err);
+
+ callback(null);
+ });
+}
+```
+
+## Keep reading
+
+* [Change Passwords](/connections/database/custom-db/templates/change-password)
+* [Delete](/connections/database/custom-db/templates/delete)
+* [Get User](/connections/database/custom-db/templates/get-user)
+* [Login](/connections/database/custom-db/templates/login)
+* [Verify](/connections/database/custom-db/templates/verify)
+* [Change Email](/connections/database/custom-db/templates/change-email)
diff --git a/articles/connections/database/custom-db/templates/delete.md b/articles/connections/database/custom-db/templates/delete.md
new file mode 100644
index 0000000000..ba548b495c
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/delete.md
@@ -0,0 +1,366 @@
+---
+description: Custom database action script templates for user deletion.
+toc: true
+topics:
+ - connections
+ - custom-database
+contentType: reference
+useCase:
+ - customize-connections
+---
+# Delete Script Templates
+
+The **Delete** script implements the function executed in order to delete the specified user identity from the legacy identity store. We recommend naming this function `deleteUser` (which will also mitigate clashes with the JavaScript `delete` keyword). The script is only used in a legacy authentication scenario if you want use Auth0 to delete users from your legacy data store.
+
+::: warning
+Deleting a user using the Auth0 Dashboard or the Auth0 Management API performs deletion of both the user profile and the user identity. If you do not implement this script correctly then this will not be done as an atomic operation, which may leave a user identity still in existence even after the user’s profile has been removed. Conversely, deleting a user identity outside of Auth0 will typically leave a disconnected (orphaned) profile in Auth0 that has no associated user identity. This may cause unpredictable issues.
+:::
+
+The `deleteUser` function should be defined as follows:
+
+```js
+function deleteUser(id, callback) {
+ // TODO: implement your script
+ return callback(null);
+}
+```
+
+| **Parameter** | **Description** |
+| --- | --- |
+| `id` | The identifier of the user. This is the connection specific identifier returned as the user_id value from either the `login` or `getUser` function. |
+| `callback` | Executed with a single parameter. The one and only parameter is an indication of status: a `null` value indicates successful operation, whereas a non `null` value indicates that some error condition occurred. |
+
+<%= include('../_includes/_bp-error-object') %>
+
+<%= include('../_includes/_panel-bcrypt-hash-encryption') %>
+
+## Sample Scripts
+
+Auth0 provides sample scripts for use with the following languages/technologies:
+
+::: next-steps
+* [JavaScript](/connections/database/custom-db/templates/delete#javascript)
+* [ASP.NET Membership Provider (MVC3 - Universal Providers)](/connections/database/custom-db/templates/delete#asp-net-membership-provider-mvc3-universal-providers-)
+* [ASP.NET Membership Provider (MVC4 - Simple Membership)](/connections/database/custom-db/templates/delete#asp-net-membership-provider-mvc4-simple-membership-)
+* [MongoDB](/connections/database/custom-db/templates/delete#mongodb)
+* [MySQL](/connections/database/custom-db/templates/delete#mysql)
+* [PostgreSQL](/connections/database/custom-db/templates/delete#postgresql)
+* [SQL Server](/connections/database/custom-db/templates/delete#sql-server)
+* [Windows Azure SQL Database](/connections/database/custom-db/templates/delete#windows-azure-sql-database)
+* [Request with Basic Auth](/connections/database/custom-db/templates/delete#request-with-basic-auth)
+:::
+
+### JavaScript
+
+```
+function remove (id, callback) {
+ // This script remove a user from your existing database.
+ // It is executed whenever a user is deleted from the Management API or Auth0 dashboard.
+ //
+ // There are two ways that this script can finish:
+ // 1. The user was removed successfully:
+ // callback(null);
+ // 2. Something went wrong while trying to reach your database:
+ // callback(new Error("my error message"));
+
+ var msg = "Please implement the Delete script for this database " +
+ "connection at https://manage.auth0.com/#/connections/database";
+ return callback(new Error(msg));
+}
+```
+
+### ASP.NET Membership Provider (MVC3 - Universal Providers)
+
+```
+function remove(id, callback) {
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true,
+ // Required to retrieve userId needed for Membership entity creation
+ rowCollectionOnRequestCompletion: true
+ }
+ });
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ // console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function(err) {
+ if (err) return callback(err);
+
+ executeDelete(['Memberships', 'Users'], function(err) {
+ if (err) return callback(err);
+
+ callback(null);
+ });
+ });
+
+ function executeDelete(tables, callback) {
+ const query = tables.map(function(table) {
+ return 'DELETE FROM ' + table + ' WHERE UserId = @UserId';
+ }).join(';');
+ const request = new Request(query, function(err) {
+ if (err) return callback(err);
+
+ callback(null);
+ });
+ request.addParameter('UserId', TYPES.VarChar, id);
+ connection.execSql(request);
+ }
+}
+```
+
+### ASP.NET Membership Provider (MVC4 - Simple Membership)
+
+```
+function remove(id, callback) {
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true,
+ // Required to retrieve userId needed for Membership entity creation
+ rowCollectionOnRequestCompletion: true
+ }
+ });
+
+ connection.on('debug', function (text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ // console.log(text);
+ }).on('errorMessage', function (text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+ executeDelete(['webpages_Membership', 'UserProfile'], function (err) {
+ if (err) return callback(err);
+ callback(null);
+ });
+ });
+
+ function executeDelete(tables, callback) {
+ const query = tables.map(function (table) {
+ return 'DELETE FROM ' + table + ' WHERE UserId = @UserId';
+ }).join(';');
+ const request = new Request(query, function (err) {
+ if (err) return callback(err);
+ callback(null);
+ });
+ request.addParameter('UserId', TYPES.VarChar, id);
+ connection.execSql(request);
+ }
+}
+```
+
+### MongoDB
+
+```
+function remove(id, callback) {
+ const MongoClient = require('mongodb@3.1.4').MongoClient;
+ const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
+
+ client.connect(function (err) {
+ if (err) return callback(err);
+
+ const db = client.db('db-name');
+ const users = db.collection('users');
+
+ users.remove({ _id: id }, function (err) {
+ client.close();
+
+ if (err) return callback(err);
+ callback(null);
+ });
+ });
+
+}
+```
+
+### MySQL
+
+```
+function remove(id, callback) {
+ const mysql = require('mysql');
+
+ const connection = mysql({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret',
+ database: 'mydb'
+ });
+
+ connection.connect();
+
+ const query = 'DELETE FROM users WHERE id = ?';
+
+ connection.query(query, [ id ], function(err) {
+ if (err) return callback(err);
+ callback(null);
+ });
+}
+```
+
+### PostgreSQL
+
+```
+function remove(id, callback) {
+ //this example uses the "pg" library
+ //more info here: https://github.com/brianc/node-postgres
+
+ const postgres = require('pg');
+
+ const conString = 'postgres://user:pass@localhost/mydb';
+ postgres.connect(conString, function (err, client, done) {
+ if (err) return callback(err);
+
+ const query = 'DELETE FROM users WHERE id = $1';
+ client.query(query, [id], function (err) {
+ // NOTE: always call `done()` here to close
+ // the connection to the database
+ done();
+
+ return callback(err);
+ });
+ });
+}
+```
+
+### SQL Server
+
+```
+function remove(id, callback) {
+ // this example uses the "tedious" library
+ // more info here: http://pekim.github.io/tedious/index.html
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'test',
+ password: 'test',
+ server: 'localhost',
+ options: {
+ database: 'mydb'
+ }
+ });
+
+ const query = 'DELETE FROM dbo.Users WHERE id = @UserId';
+
+ connection.on('debug', function (text) {
+ console.log(text);
+ }).on('errorMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+
+ const request = new Request(query, function (err) {
+ if (err) return callback(err);
+ callback(null);
+ });
+
+ request.addParameter('UserId', TYPES.VarChar, id);
+
+ connection.execSql(request);
+ });
+}
+```
+
+### Windows Azure SQL Database
+
+```
+function remove (id, callback) {
+ // this example uses the "tedious" library
+ // more info here: http://pekim.github.io/tedious/index.html
+
+ var Connection = require('tedious@1.11.0').Connection;
+ var Request = require('tedious@1.11.0').Request;
+ var TYPES = require('tedious@1.11.0').TYPES;
+
+ var connection = new Connection({
+ userName: 'your-user@your-server-id.database.windows.net',
+ password: 'the-password',
+ server: 'your-server-id.database.windows.net',
+ options: {
+ database: 'mydb',
+ encrypt: true
+ }
+ });
+
+ connection.on('debug', function (text) {
+ console.log(text);
+ }).on('errorMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) { return callback(err); }
+ var query = 'DELETE FROM users WHERE id = @UserId';
+
+ var request = new Request(query, function (err) {
+ if (err) { return callback(err); }
+ callback(null);
+ });
+
+ request.addParameter('UserId', TYPES.VarChar, id);
+
+ connection.execSql(request);
+ });
+}
+```
+
+### Request with Basic Auth
+
+```
+function remove (id, callback) {
+
+ request.del({
+ url: 'https://myserviceurl.com/users/' + id
+ // for more options check:
+ // https://github.com/mikeal/request#requestoptions-callback
+ }, function (err, response, body) {
+ if (err) { return callback(err); }
+ callback(null);
+ });
+}
+```
+
+## Keep reading
+
+* [Change Passwords](/connections/database/custom-db/templates/change-password)
+* [Create](/connections/database/custom-db/templates/create)
+* [Get User](/connections/database/custom-db/templates/get-user)
+* [Login](/connections/database/custom-db/templates/login)
+* [Verify](/connections/database/custom-db/templates/verify)
+* [Change Email](/connections/database/custom-db/templates/change-email)
diff --git a/articles/connections/database/custom-db/templates/get-user.md b/articles/connections/database/custom-db/templates/get-user.md
new file mode 100644
index 0000000000..0046674c26
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/get-user.md
@@ -0,0 +1,427 @@
+---
+description: Custom database action script templates for user search.
+toc: true
+topics:
+ - connections
+ - custom-database
+ - get-users
+contentType: reference
+useCase:
+ - customize-connections
+---
+# Get User Script Templates
+
+The **Get User** script implements the function executed to determine the current state of existence of a user. We recommend naming this function `getUser`. For automatic migration, the script is mandatory.
+
+For automatic migration, the script is executed during the password reset workflow (e.g., with a forgotten password in Universal Login). For legacy authentication, it is executed whenever the following operations occur: create user, change email, change password, and password reset.
+
+The `getUser` function should be defined as follows:
+
+```js
+function getUser(email, callback) {
+ // TODO: implement your script
+ return callback(null, profile);
+}
+```
+
+| **Parameter** | **Description** |
+| --- | --- |
+| `email` | The email address for the user as the user identifying credential. If **Requires Username** is enabled for your connection, the **Get User** script may run multiple times for some transactions (ex. Creating a user, or requesting a password reset link). In these cases the value of the parameter will sometimes be a username instead of an email. Your code should be able to handle either value and always return the same profile for a given user regardless of whether they were looked up by email or username. |
+| `callback` | Executed with up to two parameters. The first parameter is an indication of status: a `null` first parameter with a corresponding second parameter indicates that the operation executed successfully; a `null` first parameter with no corresponding second parameter indicates that no user was found, while a non `null` first parameter value indicates that some error condition occurred. If the first parameter is `null` then the second parameter should be the profile for the user in JSON format (if a user was found). If the first parameter is `null` and no user was found, or if the first parameter is non `null`, then the second parameter can be omitted. The second parameter is the `profile` for the user. This should be supplied as a JSON object in normalized user profile form. See the [**Login**](/connections/database/custom-db/templates/login#callback-profile-example) script for details. |
+
+<%= include('../_includes/_bp-error-object') %>
+
+::: warning
+When creating users, Auth0 calls the **Get User** script before the **Create** script. Be sure to implement both database action scripts if you are creating new users.
+:::
+
+## Language-specific script examples
+
+Auth0 provides sample scripts for use with the following languages/technologies:
+
+::: next-steps
+* [JavaScript](/connections/database/custom-db/templates/get-user#javascript)
+* [ASP.NET Membership Provider (MVC3 - Universal Providers)](/connections/database/custom-db/templates/get-user#asp-net-membership-provider-mvc3-universal-providers-)
+* [ASP.NET Membership Provider (MVC4 - Simple Membership)](/connections/database/custom-db/templates/get-user#asp-net-membership-provider-mvc4-simple-membership-)
+* [MongoDB](/connections/database/custom-db/templates/get-user#mongodb)
+* [MySQL](/connections/database/custom-db/templates/get-user#mysql)
+* [PostgreSQL](/connections/database/custom-db/templates/get-user#postgresql)
+* [SQL Server](/connections/database/custom-db/templates/get-user#sql-server)
+* [Windows Azure SQL Database](/connections/database/custom-db/templates/get-user#windows-azure-sql-database)
+* [Request with Basic Auth](/connections/database/custom-db/templates/get-user#request-with-basic-auth)
+* [Stormpath](/connections/database/custom-db/templates/get-user#stormpath)
+:::
+
+### JavaScript
+
+```
+function getByEmail(email, callback) {
+ // This script should retrieve a user profile from your existing database,
+ // without authenticating the user.
+ // It is used to check if a user exists before executing flows that do not
+ // require authentication (signup and password reset).
+ //
+ // There are three ways this script can finish:
+ // 1. A user was successfully found. The profile should be in the following
+ // format: https://auth0.com/docs/users/normalized/auth0/normalized-user-profile-schema.
+ // callback(null, profile);
+ // 2. A user was not found
+ // callback(null);
+ // 3. Something went wrong while trying to reach your database:
+ // callback(new Error("my error message"));
+
+ const msg = 'Please implement the Get User script for this database connection ' +
+ 'at https://manage.auth0.com/#/connections/database';
+ return callback(new Error(msg));
+}
+```
+
+### ASP.NET Membership Provider (MVC3 - Universal Providers)
+
+```
+function getByEmail(email, callback) {
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true // for Windows Azure
+ }
+ });
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function(err) {
+ if (err) return callback(err);
+
+ var user = {};
+ const query =
+ 'SELECT Memberships.UserId, Email, Users.UserName ' +
+ 'FROM Memberships INNER JOIN Users ' +
+ 'ON Users.UserId = Memberships.UserId ' +
+ 'WHERE Memberships.Email = @Username OR Users.UserName = @Username';
+
+ const getMembershipQuery = new Request(query, function(err, rowCount) {
+ if (err) return callback(err);
+ if (rowCount < 1) return callback();
+
+ callback(null, user);
+ });
+
+ getMembershipQuery.addParameter('Username', TYPES.VarChar, email);
+
+ getMembershipQuery.on('row', function(fields) {
+ user = {
+ user_id: fields.UserId.value,
+ nickname: fields.UserName.value,
+ email: fields.Email.value
+ };
+ });
+
+ connection.execSql(getMembershipQuery);
+ });
+}
+```
+
+### ASP.NET Membership Provider (MVC4 - Simple Membership)
+
+```
+function getByEmail(email, callback) {
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true // for Windows Azure
+ }
+ });
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function(err) {
+ if (err) return callback(err);
+
+ var user = {};
+ const query =
+ 'SELECT webpages_Membership.UserId, UserName, UserProfile.UserName from webpages_Membership ' +
+ 'INNER JOIN UserProfile ON UserProfile.UserId = webpages_Membership.UserId ' +
+ 'WHERE UserProfile.UserName = @Username';
+
+ const getMembershipQuery = new Request(query, function (err, rowCount) {
+ if (err) return callback(err);
+ if (rowCount < 1) return callback();
+
+ callback(null, user);
+ });
+
+ getMembershipQuery.addParameter('Username', TYPES.VarChar, email);
+
+ getMembershipQuery.on('row', function (fields) {
+ user = {
+ user_id: fields.UserId.value,
+ nickname: fields.UserName.value,
+ email: fields.UserName.value
+ };
+ });
+
+ connection.execSql(getMembershipQuery);
+ });
+}
+```
+
+### MongoDB
+
+```
+function getByEmail(email, callback) {
+ const MongoClient = require('mongodb@3.1.4').MongoClient;
+ const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
+
+ client.connect(function (err) {
+ if (err) return callback(err);
+
+ const db = client.db('db-name');
+ const users = db.collection('users');
+
+ users.findOne({ email: email }, function (err, user) {
+ client.close();
+
+ if (err) return callback(err);
+ if (!user) return callback(null, null);
+
+ return callback(null, {
+ user_id: user._id.toString(),
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+ });
+}
+```
+
+### MySQL
+
+```
+function getByEmail(email, callback) {
+ const mysql = require('mysql');
+
+ const connection = mysql({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret',
+ database: 'mydb'
+ });
+
+ connection.connect();
+
+ const query = 'SELECT id, nickname, email FROM users WHERE email = ?';
+
+ connection.query(query, [ email ], function(err, results) {
+ if (err || results.length === 0) return callback(err || null);
+
+ const user = results[0];
+ callback(null, {
+ user_id: user.id.toString(),
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+}
+```
+
+### PostgreSQL
+
+```
+function loginByEmail(email, callback) {
+ //this example uses the "pg" library
+ //more info here: https://github.com/brianc/node-postgres
+
+ const postgres = require('pg');
+
+ const conString = 'postgres://user:pass@localhost/mydb';
+ postgres.connect(conString, function (err, client, done) {
+ if (err) return callback(err);
+
+ const query = 'SELECT id, nickname, email FROM users WHERE email = $1';
+ client.query(query, [email], function (err, result) {
+ // NOTE: always call `done()` here to close
+ // the connection to the database
+ done();
+
+ if (err || result.rows.length === 0) return callback(err);
+
+ const user = result.rows[0];
+
+ return callback(null, {
+ user_id: user.id,
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+ });
+}
+```
+
+### SQL Server
+
+```
+function getByEmail(email, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'test',
+ password: 'test',
+ server: 'localhost',
+ options: {
+ database: 'mydb'
+ }
+ });
+
+ const query = 'SELECT Id, Nickname, Email FROM dbo.Users WHERE Email = @Email';
+
+ connection.on('debug', function (text) {
+ console.log(text);
+ }).on('errorMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+
+ const request = new Request(query, function (err, rowCount, rows) {
+ if (err) return callback(err);
+
+ callback(null, {
+ user_id: rows[0][0].value,
+ nickname: rows[0][1].value,
+ email: rows[0][2].value
+ });
+ });
+
+ request.addParameter('Email', TYPES.VarChar, email);
+ connection.execSql(request);
+ });
+}
+```
+
+### Windows Azure SQL Database
+
+```
+function getByEmail (name, callback) {
+ var profile = {
+ user_id: "103547991597142817347",
+ nickname: "johnfoo",
+ email: "johnfoo@gmail.com",
+ name: "John Foo",
+ given_name: "John",
+ family_name: "Foo"
+ };
+
+ callback(null, profile);
+}
+```
+
+### Request with Basic Auth
+
+```
+function loginByEmail(email, callback) {
+ const request = require('request');
+
+ request.get({
+ url: 'https://myserviceurl.com/users-by-email/' + email
+ //for more options check:
+ //https://github.com/mikeal/request#requestoptions-callback
+ }, function(err, response, body) {
+ if (err) return callback(err);
+
+ const user = JSON.parse(body);
+
+ callback(null, {
+ user_id: user.user_id.toString(),
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+}
+```
+
+### Stormpath
+
+```
+function getByEmail(email, callback) {
+ // Replace the YOUR-STORMPATH-CLIENT-ID with your Stormpath ID
+ var url = 'https://api.stormpath.com/v1/applications/{YOUR-STORMPATH-CLIENT-ID}/accounts';
+ // Add your Stormpath API Client ID and Secret
+ var apiCredentials = {
+ user : 'YOUR-STORMPATH-API-ID',
+ password: 'YOUR-STORMPATH-API-SECRET'
+ };
+
+ // Make a GET request to find a user by email
+ request({
+ url: url,
+ method: 'GET',
+ auth: apiCredentials,
+ qs: { q: email },
+ json: true
+ }, function (error, response, body) {
+ if (response.statusCode !== 200) return callback();
+
+ var user = body.items[0];
+
+ if (!user) return callback();
+
+ var id = user.href.replace('https://api.stormpath.com/v1/accounts/', '');
+
+ return callback(null, {
+ user_id: id,
+ username: user.username,
+ email: user.email,
+ email_verified: true
+ // Add any additional fields you would like to carry over from Stormpath
+ });
+ });
+}
+```
+
+## Keep reading
+
+* [Change Passwords](/connections/database/custom-db/templates/change-password)
+* [Create](/connections/database/custom-db/templates/create)
+* [Delete](/connections/database/custom-db/templates/delete)
+* [Login](/connections/database/custom-db/templates/login)
+* [Verify](/connections/database/custom-db/templates/verify)
+* [Change Email](/connections/database/custom-db/templates/change-email)
diff --git a/articles/connections/database/custom-db/templates/index.md b/articles/connections/database/custom-db/templates/index.md
new file mode 100644
index 0000000000..66a1318d9f
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/index.md
@@ -0,0 +1,68 @@
+---
+description: Learn about custom database action script templates.
+topics:
+ - connections
+ - custom-database
+ - templates
+contentType:
+ - index
+ - concept
+useCase:
+ - customize-connections
+ - script-templates
+---
+# Custom Database Action Script Templates
+
+<%= include('../_includes/_panel-feature-availability') %>
+
+If you have your own database (known as a legacy data store in Auth0) containing user identity data, you can use it as an identity provider to authenticate users.
+You create and configure the connection to your legacy data store as a custom database in Auth0. You can choose to migrate data to Auth0's data store from your legacy database incrementally over time, or you can continue to use it without migrating data. We provide script templates to perform functions on the custom database that you can use and customize.
+
+There are two different types of custom database scripts:
+
+* **Automatic Migration**: Whenever a user logs into Auth0, if the user is not yet in Auth0, the script will check the legacy database to see if the user exists there. If found and the **Import users to Auth0** flag is turned on, the user data migrates the user to Auth0 data store. This capability is sometimes called **trickle migration** or **lazy migration**.
+
+* **Legacy Database**: Auth0 will always query the underlying database when a user tries to log in, is created, changes their password, verifies their email, or is deleted. If found and the **Import users to Auth0** flag is **not** turned on, user data stays in the legacy database and does **not** migrate to Auth0.
+
+Auth0 provides the following custom database action scripts:
+
+* [Change Passwords](/connections/database/custom-db/templates/change-password)
+* [Create](/connections/database/custom-db/templates/create)
+* [Delete](/connections/database/custom-db/templates/delete)
+* [Get User](/connections/database/custom-db/templates/get-user)
+* [Login](/connections/database/custom-db/templates/login)
+* [Verify](/connections/database/custom-db/templates/verify)
+* [Change Email](/connections/database/custom-db/templates/change-email)
+
+<%= include('../../../../_includes/_ip_whitelist') %>
+
+## Script execution
+
+As described in the [Custom Database Connections Overview](/connections/database/custom-db/custom-db-connection-overview#how-it-works), a custom database connection type allows you to configure action scripts: custom code that is used when interfacing with your legacy identity store. Each action script is essentially a named JavaScript function that is passed a number of parameters, with the name of the function and the parameters passed depending on the script.
+
+### Limits
+
+Action script execution supports the asynchronous nature of JavaScript, and constructs such as [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) objects can be used. Asynchronous processing effectively results in suspension pending completion of an operation, and an Auth0 serverless Webtask container typically has a 20-second execution limit, after which the container may be recycled. Recycling a container due to this limit will prematurely terminate operation, ultimately resulting in an error condition being returned (as well as resulting in a potential reset of the `global` object).
+
+### Completion and the `callback` function
+
+The `callback` function supplied to each action script effectively acts as a signal to indicate completion of operation. An action script should complete immediately following a call to the `callback` function (either implicitly or by explicitly executing a JavaScript return statement) and should refrain from any other operation.
+
+::: warning
+The Auth0 supplied `callback` function must be called exactly **once**; calling the function more than once within an action script will lead to unpredictable results and/or errors.
+:::
+
+::: note
+Where `callback` is executed with no parameters, as in `callback()`, the implication is that function has been called as though `callback(null)` had been executed.
+:::
+
+If an action script uses asynchronous processing, then a call to the `callback` function must be deferred to the point where asynchronous processing completes, and must be the final thing called. Asynchronous execution will result in a JavaScript `callback` being executed after the asynchronous operation is complete; this callback is typically fired at some point after the main (synchronous) body of a JavaScript function completes.
+
+::: warning
+Failure to execute the `callback` function will result in a stall of execution, and ultimately in an error condition being returned. The action script must call the `callback` function exactly once: the `callback` function must be called at least once in order to prevent stall of execution, however it must not be called more than once otherwise unpredictable results and/or errors will occur.
+:::
+
+## Keep reading
+
+* [Custom Database Action Script Execution Best Practices](/best-practices/custom-db-connections/execution)
+* [Handle Errors and Troubleshoot Your Custom DB Scripts](/connections/database/custom-db/error-handling)
diff --git a/articles/connections/database/custom-db/templates/login.md b/articles/connections/database/custom-db/templates/login.md
new file mode 100644
index 0000000000..f20948b312
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/login.md
@@ -0,0 +1,709 @@
+---
+description: Custom database action script templates for user login.
+toc: true
+topics:
+ - connections
+ - custom-database
+contentType: reference
+useCase:
+ - customize-connections
+---
+# Login Script Templates
+
+The **Login** script implements the function executed each time a user is required to authenticate. We recommend naming this function `login`. The `login` function is typically used during the Universal Login workflow, but is also applicable in other authentication flow scenarios (such as [Resource Owner Password Grant](/api-auth/tutorials/password-grant)). The script is required for both legacy authentication and for automatic migration.
+
+The `login` function should be defined as follows:
+
+```js
+function login(userNameOrEmail, password, callback) {
+ // TODO: implement your script
+ return callback(null, profile);
+}
+```
+
+| **Parameter** | **Description** |
+| --- | --- |
+| `userNameOrEmail` | The identification credential for the user typically either the email address for the user or the name associated with the user. With default out-of-box Universal Login, support for the use of `username` during login is available only if the **Requires Username** setting is enabled for the database connection. |
+| `password` | Passed to the `login` script in plain text. Do not store it or transport it anywhere in its vanilla form. Use `bcrypt` as described below. |
+| `callback` | Executed with up to two parameters. The first parameter is an indication of status: a `null` first parameter with a corresponding second parameter indicates that the operation executed successfully, while a non `null` first parameter value indicates that some error condition occurred. If the first parameter is `null` then the second parameter is the profile for the user in JSON format. If the first parameter is non `null` then the second parameter can be omitted. The second parameter is the `profile` for the user. This should be supplied as a JSON object in normalized user profile form. See the example below. |
+
+<%= include('../_includes/_bp-error-object') %>
+
+<%= include('../_includes/_panel-bcrypt-hash-encryption') %>
+
+## `callback` `profile` parameter example
+
+The second parameter provided to the `callback` function should be the profile for the user. This should be supplied as a JSON object in normalized user profile form.
+
+::: warning
+The profile returned by the `login` script for a user should be consistent with the profile returned in the `getUser` script, and vice-versa.
+:::
+
+Additionally, you can also provide metadata for a user as part of the user profile returned. The following is an example of the profile object that can be returned for a user.
+
+```js
+{
+ "username": "",
+ "user_id": "",
+ "email": "jane.doe@example.com",
+ "email_verified": false,
+ "user_metadata": {
+ "language": "en"
+ },
+ "app_metadata": {
+ "plan": "full"
+ },
+ "mfa_factors": [
+ {
+ "phone": {
+ "value": "+15551234567"
+ }
+ },
+ ]
+}
+```
+
+| **Parameter** | Description |
+| --- | --- |
+| `username` | If a custom database connection type has **Requires Username** as an enabled setting then the profile returned for the user must include a `username`. If the setting is not enabled then `username` is optional and can be omitted. |
+| `user_id` | The `user_id` value must be specified and provides the unique identifier for a user. For the `auth0` strategy, the strategy used to define a custom database connection, Auth0 automatically decorates whatever `user_id` value is supplied by prefixing the text `auth0|` in order to create the `user_id` in the root of the normalized user profile. The `user_id` value supplied will appear in it’s undecorated form in the identities array associated with the user profile in Auth0. The `user_id` value specified must be unique across all database connections defined in an Auth0 tenant. Failure to observe this will result in user identifier collision which will lead to unpredictable operation. One way to avoid this is to explicitly prefix the supplied `user_id` with the name of, or pseudonym for, the connection (omitting any whitespace). The `user_id` value must also be consistent for any given user; the value returned by the **Login** script must also be consistent with the value returned by the **Get User** script, and vice-versa. Failure to observe this requirement can lead to duplicate Auth0 user profiles for a user, duplicate identities for any user migrated via automatic migration, and/or unpredictable results when it comes to user operations. |
+| `email` | An `email` value should also be specified. While an email address is not mandatory for a user, much of Auth0 out-of-box functionality such as password reset, requires that a user has a valid and verified email address. Email addresses should be returned consistently for all scripts and should also be unique within the context of a single custom database connection (for automatic migration scenarios). Failure to observe either of these requirements will typically lead to unpredictable results when it comes to user operation. |
+| `mfa_factors` | (Optional) A list of [MFA enrollments](/mfa) for the imported user, which prevents the need for users to re-enroll in MFA. This field currently supports [SMS](/mfa/concepts/mfa-factors#sms-notifications), [Voice](/mfa/concepts/mfa-factors#voice-notifications), [OTP](/mfa/concepts/mfa-factors#one-time-passwords), and [email](/mfa/concepts/mfa-factors#email-notifications) based factors.|
+
+::: panel Best Practice
+While a user does not need to use an email address to login, it’s recommended best practice that they have an email address defined against their user profile. This ensures that Auth0 out-of-box functionality works as designed.
+:::
+
+For a legacy authentication scenario, you can also enable the `Sync user profile at each login` option in the settings for a custom database connection. This allows attribute updates in the Auth0 user profile each time a login for the user occurs for attributes that would otherwise not be available for update via the Auth0 Management API. For legacy authentication scenarios there are a number of root profile attributes which cannot be updated directly via the Management API.
+
+::: note
+In order to update `name`, `nickname`, `given_name`, `family_name`, and/or `picture` attributes associated with the root of the normalized user profile, you must configure user profile sync so that user attributes will be updated from the identity provider. Auth0 does not support update of these attributes for a custom database connection used for legacy authentication.
+:::
+
+## Language-specific script examples
+
+Auth0 provides sample scripts for use with the following languages/technologies:
+
+::: next-steps
+* [JavaScript](/connections/database/custom-db/templates/login#javascript)
+* [ASP.NET Membership Provider (MVC3 - Universal Providers)](/connections/database/custom-db/templates/login#asp-net-membership-provider-mvc3-universal-providers-)
+* [ASP.NET Membership Provider (MVC4 - Simple Membership)](/connections/database/custom-db/templates/login#asp-net-membership-provider-mvc4-simple-membership-)
+* [MongoDB](/connections/database/custom-db/templates/login#mongodb)
+* [MySQL](/connections/database/custom-db/templates/login#mysql)
+* [PostgreSQL](/connections/database/custom-db/templates/login#postgresql)
+* [SQL Server](/connections/database/custom-db/templates/login#sql-server)
+* [Windows Azure SQL Database](/connections/database/custom-db/templates/login#windows-azure-sql-database)
+* [Request with Basic Auth](/connections/database/custom-db/templates/login#request-with-basic-auth)
+* [Stormpath](/connections/database/custom-db/templates/login#stormpath)
+:::
+
+### JavaScript
+
+```
+function login(email, password, callback) {
+ // This script should authenticate a user against the credentials stored in
+ // your database.
+ // It is executed when a user attempts to log in or immediately after signing
+ // up (as a verification that the user was successfully signed up).
+ //
+ // Everything returned by this script will be set as part of the user profile
+ // and will be visible by any of the tenant admins. Avoid adding attributes
+ // with values such as passwords, keys, secrets, etc.
+ //
+ // The `password` parameter of this function is in plain text. It must be
+ // hashed/salted to match whatever is stored in your database. For example:
+ //
+ // var bcrypt = require('bcrypt@0.8.5');
+ // bcrypt.compare(password, dbPasswordHash, function(err, res)) { ... }
+ //
+ // There are three ways this script can finish:
+ // 1. The user's credentials are valid. The returned user profile should be in
+ // the following format: https://auth0.com/docs/users/normalized/auth0/normalized-user-profile-schema
+ // var profile = {
+ // user_id: ..., // user_id is mandatory
+ // email: ...,
+ // [...]
+ // };
+ // callback(null, profile);
+ // 2. The user's credentials are invalid
+ // callback(new WrongUsernameOrPasswordError(email, "my error message"));
+ // 3. Something went wrong while trying to reach your database
+ // callback(new Error("my error message"));
+ //
+ // A list of Node.js modules which can be referenced is available here:
+ //
+ // https://tehsis.github.io/webtaskio-canirequire/
+
+ const msg = 'Please implement the Login script for this database connection ' +
+ 'at https://manage.auth0.com/#/connections/database';
+ return callback(new Error(msg));
+}
+```
+
+### ASP.NET Membership Provider (MVC3 - Universal Providers)
+
+```
+function login(email, password, callback) {
+ const crypto = require('crypto');
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true // for Windows Azure
+ }
+ });
+
+ /**
+ * hashPassword
+ *
+ * This function creates a hashed version of the password to store in the database.
+ *
+ * @password {[string]} the password entered by the user
+ * @return {[string]} the hashed password
+ */
+ function hashPassword(password, salt) {
+ // the default implementation uses HMACSHA256 and since Key length is 64
+ // and default salt is 16 bytes, Membership will fill the buffer repeating the salt
+ const key = Buffer.concat([salt, salt, salt, salt]);
+ const hmac = crypto.createHmac('sha256', key);
+ hmac.update(Buffer.from(password, 'ucs2'));
+
+ return hmac.digest('base64');
+ }
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function(err) {
+ if (err) return callback(err);
+
+ getMembershipUser(email, function(err, user) {
+ if (err || !user || !user.profile || !user.password) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ const salt = Buffer.from(user.password.salt, 'base64');
+
+ if (hashPassword(password, salt).toString('base64') !== user.password.password) {
+ return callback(new WrongUsernameOrPasswordError(email));
+ }
+
+ callback(null, user.profile);
+ });
+ });
+
+
+ // Membership Provider implementation used on Microsoft.AspNet.Providers NuGet
+
+ /**
+ * getMembershipUser
+ *
+ * This function gets a username or email and returns a the user membership provider
+ * info, password hashes and salt
+ *
+ * @usernameOrEmail {[string]} the username or email, the method will do a
+ * query on both with an OR
+ *
+ * @callback {[Function]} first argument will be the Error if any,
+ * and second argument will be a user object
+ */
+ function getMembershipUser(usernameOrEmail, done) {
+ var user = null;
+ const query =
+ 'SELECT Memberships.UserId, Email, Users.UserName, Password ' +
+ 'FROM Memberships INNER JOIN Users ' +
+ 'ON Users.UserId = Memberships.UserId ' +
+ 'WHERE Memberships.Email = @Username OR Users.UserName = @Username';
+
+ const getMembershipQuery = new Request(query, function(err, rowCount) {
+ if (err || rowCount < 1) return done(err);
+
+ done(err, user);
+ });
+
+ getMembershipQuery.addParameter('Username', TYPES.VarChar, usernameOrEmail);
+
+ getMembershipQuery.on('row', function(fields) {
+ user = {
+ profile: {
+ user_id: fields.UserId.value,
+ nickname: fields.UserName.value,
+ email: fields.Email.value,
+ },
+ password: {
+ password: fields.Password.value,
+ salt: fields.PasswordSalt.value
+ }
+ };
+ });
+
+ connection.execSql(getMembershipQuery);
+ }
+}
+```
+
+### ASP.NET Membership Provider (MVC4 - Simple Membership)
+
+```
+function login(email, password, callback) {
+ const crypto = require('crypto');
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true // for Windows Azure
+ }
+ });
+
+ function fixedTimeComparison(a, b) {
+ var mismatch = (a.length === b.length ? 0 : 1);
+ if (mismatch) {
+ b = a;
+ }
+
+ for (var i = 0, il = a.length; i < il; ++i) {
+ const ac = a.charCodeAt(i);
+ const bc = b.charCodeAt(i);
+ mismatch += (ac === bc ? 0 : 1);
+ }
+
+ return (mismatch === 0);
+ }
+
+
+ /**
+ * validatePassword
+ *
+ * This function gets the password entered by the user, and the original password
+ * hash and salt from database and performs an HMAC SHA256 hash.
+ *
+ * @password {[string]} the password entered by the user
+ * @originalHash {[string]} the original password hashed from the database
+ * (including the salt).
+ * @return {[bool]} true if password validates
+ */
+ function validatePassword(password, originalHash, callback) {
+ const iterations = 1000;
+ const hashBytes = Buffer.from(originalHash, 'base64');
+ const salt = hashBytes.slice(1, 17);
+ const hash = hashBytes.slice(17, 49);
+ crypto.pbkdf2(password, salt, iterations, hash.length, 'sha1', function(err, hashed) {
+ if (err) return callback(err);
+
+ const hashedBase64 = Buffer.from(hashed, 'binary').toString('base64');
+ const isValid = fixedTimeComparison(hash.toString('base64'), hashedBase64);
+
+ return callback(null, isValid);
+ });
+ }
+
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function(err) {
+ if (err) return callback(err);
+ getMembershipUser(email, function(err, user) {
+ if (err || !user || !user.profile) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ validatePassword(password, user.password, function(err, isValid) {
+ if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ callback(null, user.profile);
+ });
+ });
+ });
+
+
+ // Membership Provider implementation used on Microsoft.AspNet.Providers NuGet
+
+ /**
+ * getMembershipUser
+ *
+ * This function gets a username or email and returns a user info, password hashes and salt
+ *
+ * @usernameOrEamil {[string]} the username or email, the method will do a query
+ * on both with an OR
+ * @callback {[Function]} first argument will be the Error if any, and second
+ * argument will be a user object
+ */
+ function getMembershipUser(usernameOrEmail, done) {
+ var user = null;
+ const query =
+ 'SELECT webpages_Membership.UserId, UserName, UserProfile.UserName, Password from webpages_Membership ' +
+ 'INNER JOIN UserProfile ON UserProfile.UserId = webpages_Membership.UserId ' +
+ 'WHERE UserProfile.UserName = @Username';
+
+ const getMembershipQuery = new Request(query, function(err, rowCount) {
+ if (err || rowCount < 1) return done(err);
+
+ done(err, user);
+ });
+
+ getMembershipQuery.addParameter('Username', TYPES.VarChar, usernameOrEmail);
+
+ getMembershipQuery.on('row', function(fields) {
+ user = {
+ profile: {
+ user_id: fields.UserId.value,
+ nickname: fields.UserName.value,
+ email: fields.UserName.value,
+ },
+ password: fields.Password.value
+ };
+ });
+
+ connection.execSql(getMembershipQuery);
+ }
+}
+```
+
+### MongoDB
+
+```
+function login(email, password, callback) {
+ const bcrypt = require('bcrypt');
+ const MongoClient = require('mongodb@3.1.4').MongoClient;
+ const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
+
+ client.connect(function (err) {
+ if (err) return callback(err);
+
+ const db = client.db('db-name');
+ const users = db.collection('users');
+
+ users.findOne({ email: email }, function (err, user) {
+ if (err || !user) {
+ client.close();
+ return callback(err || new WrongUsernameOrPasswordError(email));
+ }
+
+ bcrypt.compare(password, user.password, function (err, isValid) {
+ client.close();
+
+ if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ return callback(null, {
+ user_id: user._id.toString(),
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+ });
+ });
+}
+```
+
+### MySQL
+
+```
+function login(email, password, callback) {
+ const mysql = require('mysql');
+ const bcrypt = require('bcrypt');
+
+ const connection = mysql({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret',
+ database: 'mydb'
+ });
+
+ connection.connect();
+
+ const query = 'SELECT id, nickname, email, password FROM users WHERE email = ?';
+
+ connection.query(query, [ email ], function(err, results) {
+ if (err) return callback(err);
+ if (results.length === 0) return callback(new WrongUsernameOrPasswordError(email));
+ const user = results[0];
+
+ bcrypt.compare(password, user.password, function(err, isValid) {
+ if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ callback(null, {
+ user_id: user.id.toString(),
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+ });
+}
+```
+
+### PostgreSQL
+
+```
+function login(email, password, callback) {
+ //this example uses the "pg" library
+ //more info here: https://github.com/brianc/node-postgres
+
+ const bcrypt = require('bcrypt');
+ const postgres = require('pg');
+
+ const conString = 'postgres://user:pass@localhost/mydb';
+ postgres.connect(conString, function (err, client, done) {
+ if (err) return callback(err);
+
+ const query = 'SELECT id, nickname, email, password FROM users WHERE email = $1';
+ client.query(query, [email], function (err, result) {
+ // NOTE: always call `done()` here to close
+ // the connection to the database
+ done();
+
+ if (err || result.rows.length === 0) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ const user = result.rows[0];
+
+ bcrypt.compare(password, user.password, function (err, isValid) {
+ if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ return callback(null, {
+ user_id: user.id,
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+ });
+ });
+}
+```
+
+### SQL Server
+
+```
+function login(email, password, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+ const bcrypt = require('bcrypt');
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'test',
+ password: 'test',
+ server: 'localhost',
+ options: {
+ database: 'mydb'
+ }
+ });
+
+ const query = 'SELECT Id, Nickname, Email, Password FROM dbo.Users WHERE Email = @Email';
+
+ connection.on('debug', function (text) {
+ console.log(text);
+ }).on('errorMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+
+ const request = new Request(query, function (err, rowCount, rows) {
+ if (err || rowCount < 1) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ bcrypt.compare(password, rows[0][3].value, function (err, isValid) {
+ if (err || !isValid) return callback(err || new WrongUsernameOrPasswordError(email));
+
+ callback(null, {
+ user_id: rows[0][0].value,
+ nickname: rows[0][1].value,
+ email: rows[0][2].value
+ });
+ });
+ });
+
+ request.addParameter('Email', TYPES.VarChar, email);
+ connection.execSql(request);
+ });
+}
+```
+
+### Windows Azure SQL Database
+
+```
+function login(email, password, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+ var Connection = require('tedious@1.11.0').Connection;
+ var Request = require('tedious@1.11.0').Request;
+ var TYPES = require('tedious@1.11.0').TYPES;
+ var bcrypt = require('bcrypt');
+
+ var connection = new Connection({
+ userName: 'your-user@your-server-id.database.windows.net',
+ password: 'the-password',
+ server: 'your-server-id.database.windows.net',
+ options: {
+ database: 'mydb',
+ encrypt: true,
+ rowCollectionOnRequestCompletion: true
+ }
+ });
+
+ var query = "SELECT Id, Email, Password " +
+ "FROM dbo.Users WHERE Email = @Email";
+
+ connection.on('debug', function (text) {
+ // Uncomment next line in order to enable debugging messages
+ // console.log(text);
+ }).on('errorMessage', function (text) {
+ console.log(JSON.stringify(text, null, 2));
+ return callback(text);
+ }).on('infoMessage', function (text) {
+ // Uncomment next line in order to enable information messages
+ // console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) { return callback(err); }
+
+ var request = new Request(query, function (err, rowCount, rows) {
+ if (err) {
+ callback(new Error(err));
+ } else if (rowCount < 1) {
+ callback(new WrongUsernameOrPasswordError(email));
+ } else {
+ bcrypt.compare(password, rows[0][2].value, function (err, isValid) {
+ if (err) { callback(new Error(err)); }
+ else if (!isValid) { callback(new WrongUsernameOrPasswordError(email)); }
+ else {
+ callback(null, {
+ user_id: rows[0][0].value,
+ email: rows[0][1].value
+ });
+ }
+ });
+ }
+ });
+
+ request.addParameter('Email', TYPES.VarChar, email);
+ connection.execSql(request);
+ });
+}
+```
+
+### Request with Basic Auth
+
+```
+function login(email, password, callback) {
+ const request = require('request');
+
+ request.get({
+ url: 'https://myserviceurl.com/profile',
+ auth: {
+ username: email,
+ password: password
+ }
+ //for more options check:
+ //https://github.com/mikeal/request#requestoptions-callback
+ }, function(err, response, body) {
+ if (err) return callback(err);
+ if (response.statusCode === 401) return callback();
+ const user = JSON.parse(body);
+
+ callback(null, {
+ user_id: user.user_id.toString(),
+ nickname: user.nickname,
+ email: user.email
+ });
+ });
+}
+```
+
+### Stormpath
+
+```
+function login(username, password, callback) {
+ // Replace the YOUR-STORMPATH-CLIENT-ID with your Stormpath ID
+ var url = 'https://api.stormpath.com/v1/applications/{YOUR-STORMPATH-CLIENT-ID}/loginAttempts';
+ // Add your Stormpath API Client ID and Secret
+ var apiCredentials = {
+ user : 'YOUR-STORMPATH-API-ID',
+ password: 'YOUR-STORMPATH-API-SECRET'
+ };
+
+ // Stormpath requires the user credentials be passed in as a base64 encoded message
+ var credentials = Buffer.from(username + ':' + password).toString('base64');
+
+ // Make a POST request to authenticate a user
+ request({
+ url: url,
+ method: 'POST',
+ auth: apiCredentials,
+ json: {
+ type: 'basic',
+ // Passing in the base64 encoded credentials
+ value: credentials
+ }
+ }, function (error, response, body) {
+ // If response is successful we'll continue
+ if (response.statusCode !== 200) return callback();
+ // A successful response will return a URL to get the user information
+ var accountUrl = body.account.href;
+
+ // Make a second request to get the user info.
+ request({
+ url: accountUrl,
+ auth: apiCredentials,
+ json: true
+ }, function (errorUserInfo, responseUserInfo, bodyUserInfo) {
+ // If we get a successful response, we'll process it
+ if (responseUserInfo.statusCode !== 200) return callback();
+
+ // To get the user identifier, we'll strip out the Stormpath API
+ var id = bodyUserInfo.href.replace('https://api.stormpath.com/v1/accounts/', '');
+
+ // Finally, we'll set the data we want to store in Auth0 and migrate the user
+ return callback(null, {
+ user_id : id,
+ username: bodyUserInfo.username,
+ email: bodyUserInfo.email,
+ // We set the users email_verified to true as we assume if they were a valid
+ // user in Stormpath, they have already verified their email
+ // If this field is not set, the user will get an email asking them to verify
+ // their account. You can decide how to handle this for your use case
+ email_verified: true
+ // Add any additional fields you would like to carry over from Stormpath
+ });
+ });
+ });
+}
+```
+
+## Keep reading
+
+* [Change Passwords](/connections/database/custom-db/templates/change-password)
+* [Create](/connections/database/custom-db/templates/create)
+* [Delete](/connections/database/custom-db/templates/delete)
+* [Get User](/connections/database/custom-db/templates/get-user)
+* [Verify](/connections/database/custom-db/templates/verify)
+* [Change Email](/connections/database/custom-db/templates/change-email)
diff --git a/articles/connections/database/custom-db/templates/verify.md b/articles/connections/database/custom-db/templates/verify.md
new file mode 100644
index 0000000000..0fe7bca960
--- /dev/null
+++ b/articles/connections/database/custom-db/templates/verify.md
@@ -0,0 +1,433 @@
+---
+description: Custom database action script templates for user verification.
+toc: true
+topics:
+ - connections
+ - custom-database
+contentType: reference
+useCase:
+ - customize-connections
+---
+# Verify Users Script Templates
+
+The **Verify** script implements the function executed to mark the verification status of a user’s email address in the legacy identity store. Email verification status information is typically returned via `email_verified` as part of any user profile information returned (see [Login](/connections/database/custom-db/templates/login) and [Get User](/connections/database/custom-db/templates/get-user) for further details). The script is executed when a user clicks on the link in the verification email sent by Auth0. We recommend naming this function `verify`. The script is only used in a legacy authentication scenario, and must be implemented if support is required for Auth0 email verification functionality.
+
+While it’s not mandatory to implement the `verify` function, it is a recommended best practice. The function is required to support user email address verification, and a verified email address for a user is critical to a number of the workflow scenarios in Auth0. Implementing the script will provide support for these workflows out-of-box.
+
+::: note
+The `verify` function is called when a user clicks on the link in the verification email sent by Auth0. Change in email verification status influenced by other operations, such as via user profile modification in the Auth0 Dashboard, is performed via the [Change Email](/connections/database/custom-db/templates/change-email) script.
+:::
+
+The `verify` function should be defined as follows:
+
+```js
+function verify(email, callback) {
+ // TODO: implement your script
+ return callback(null, JSON Object);
+}
+```
+
+| **Parameter** | **Description** |
+| --- | --- |
+| `email` | The email address for the user as the user identifying credential. |
+| `callback` | Executed with up to two parameters. The first parameter is an indication of status: a `null` first parameter with a corresponding second parameter indicates that the operation executed successfully, while a non `null` first parameter value indicates that some error condition occurred. |
+
+## `callback` example
+
+If the first parameter is `null` then the second parameter should be a JSON object in a format similar to the following:
+
+```js
+{
+ "user_id": "",
+ "email": "jane.doe@example.com",
+ "email_verified": true
+}
+```
+
+<%= include('../_includes/_bp-error-object') %>
+
+## Language-specific script examples
+
+Auth0 provides sample scripts for use with the following languages/technologies:
+
+* [JavaScript](#javascript)
+* [ASP.NET Membership Provider (MVC3 - Universal Providers)](#asp-net-membership-provider-mvc3-universal-providers-)
+* [ASP.NET Membership Provider (MVC4 - Simple Membership)](#asp-net-membership-provider-mvc4-simple-membership-)
+* [MongoDB](#mongodb)
+* [MySQL](#mysql)
+* [PostgreSQL](#postgresql)
+* [SQL Server](#sql-server)
+* [Windows Azure SQL Database](#windows-azure-sql-database)
+* [Request with Basic Auth](#request-with-basic-auth)
+
+### JavaScript
+
+```
+function verify(email, callback) {
+ // This script should mark the current user's email address as verified in
+ // your database.
+ // It is executed whenever a user clicks the verification link sent by email.
+ // These emails can be customized at https://manage.auth0.com/#/emails.
+ // It is safe to assume that the user's email already exists in your database,
+ // because verification emails, if enabled, are sent immediately after a
+ // successful signup.
+ //
+ // There are two ways that this script can finish:
+ // 1. The user's email was verified successfully
+ // callback(null, true);
+ // 2. Something went wrong while trying to reach your database:
+ // callback(new Error("my error message"));
+ //
+ // If an error is returned, it will be passed to the query string of the page
+ // where the user is being redirected to after clicking the verification link.
+ // For example, returning `callback(new Error("error"))` and redirecting to
+ // https://example.com would redirect to the following URL:
+ // https://example.com?email=alice%40example.com&message=error&success=false
+
+ const msg = 'Please implement the Verify script for this database connection ' +
+ 'at https://manage.auth0.com/#/connections/database';
+ return callback(new Error(msg));
+}
+```
+
+### ASP.NET Membership Provider (MVC3 - Universal Providers)
+
+```
+function verify(email, callback) {
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true,
+ // Required to retrieve userId needed for Membership entity creation
+ rowCollectionOnRequestCompletion: true
+ }
+ });
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function(err) {
+ if (err) return callback(err);
+
+ verifyMembershipUser(email, function(err, wasUpdated) {
+ if (err) return callback(err); // this will return a 500
+
+ callback(null, wasUpdated);
+ });
+ });
+
+ function verifyMembershipUser(email, callback) {
+ // isApproved field is the email verification flag
+ const updateMembership =
+ 'UPDATE Memberships SET isApproved = \'true\' ' +
+ 'WHERE isApproved = \'false\' AND Email = @Email';
+
+ const updateMembershipQuery = new Request(updateMembership, function(err, rowCount) {
+ if (err) {
+ return callback(err);
+ }
+ callback(null, rowCount > 0);
+ });
+
+ updateMembershipQuery.addParameter('Email', TYPES.VarChar, email);
+
+ connection.execSql(updateMembershipQuery);
+ }
+}
+```
+
+### ASP.NET Membership Provider (MVC4 - Simple Membership)
+
+```
+function verify (email, callback) {
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'the username',
+ password: 'the password',
+ server: 'the server',
+ options: {
+ database: 'the db name',
+ encrypt: true,
+ // Required to retrieve userId needed for Membership entity creation
+ rowCollectionOnRequestCompletion: true
+ }
+ });
+
+ connection.on('debug', function(text) {
+ // if you have connection issues, uncomment this to get more detailed info
+ //console.log(text);
+ }).on('errorMessage', function(text) {
+ // this will show any errors when connecting to the SQL database or with the SQL statements
+ console.log(JSON.stringify(text));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+ verifyMembershipUser(email, function(err, wasUpdated) {
+ if (err) return callback(err); // this will return a 500
+
+ callback(null, wasUpdated);
+ });
+ });
+
+ function findUserId(email, callback) {
+ const findUserIdFromEmail =
+ 'SELECT UserProfile.UserId FROM ' +
+ 'UserProfile INNER JOIN webpages_Membership ' +
+ 'ON UserProfile.UserId = webpages_Membership.UserId ' +
+ 'WHERE UserName = @Username';
+
+ const findUserIdFromEmailQuery = new Request(findUserIdFromEmail, function (err, rowCount, rows) {
+ if (err || rowCount < 1) return callback(err);
+
+ const userId = rows[0][0].value;
+
+ callback(null, userId);
+ });
+
+ findUserIdFromEmailQuery.addParameter('Username', TYPES.VarChar, email);
+
+ connection.execSql(findUserIdFromEmailQuery);
+ }
+
+ function verifyMembershipUser(email, callback) {
+ findUserId(email, function (err, userId) {
+ if (err || !userId) return callback(err);
+
+ // isConfirmed field is the email verification flag
+ const updateMembership =
+ 'UPDATE webpages_Membership SET isConfirmed = \'true\' ' +
+ 'WHERE isConfirmed = \'false\' AND UserId = @UserId';
+
+ const updateMembershipQuery = new Request(updateMembership, function (err, rowCount) {
+ return callback(err, rowCount > 0);
+ });
+
+ updateMembershipQuery.addParameter('UserId', TYPES.VarChar, userId);
+
+ connection.execSql(updateMembershipQuery);
+ });
+ }
+}
+```
+
+### MongoDB
+
+```
+function verify (email, callback) {
+ const MongoClient = require('mongodb@3.1.4').MongoClient;
+ const client = new MongoClient('mongodb://user:pass@mymongoserver.com');
+
+ client.connect(function (err) {
+ if (err) return callback(err);
+
+ const db = client.db('db-name');
+ const users = db.collection('users');
+ const query = { email: email, email_verified: false };
+
+ users.update(query, { $set: { email_verified: true } }, function (err, count) {
+ client.close();
+
+ if (err) return callback(err);
+ callback(null, count > 0);
+ });
+ });
+}
+```
+
+### MySQL
+
+```
+function verify(email, callback) {
+ const mysql = require('mysql');
+
+ const connection = mysql({
+ host: 'localhost',
+ user: 'me',
+ password: 'secret',
+ database: 'mydb'
+ });
+
+ connection.connect();
+
+ const query = 'UPDATE users SET email_Verified = true WHERE email_Verified = false AND email = ?';
+
+ connection.query(query, [ email ], function(err, results) {
+ if (err) return callback(err);
+
+ callback(null, results.length > 0);
+ });
+
+}
+```
+
+### PostgreSQL
+
+```
+function verify (email, callback) {
+ //this example uses the "pg" library
+ //more info here: https://github.com/brianc/node-postgres
+
+ const postgres = require('pg');
+
+ const conString = 'postgres://user:pass@localhost/mydb';
+ postgres.connect(conString, function (err, client, done) {
+ if (err) return callback(err);
+
+ const query = 'UPDATE users SET email_Verified = true WHERE email_Verified = false AND email = $1';
+ client.query(query, [email], function (err, result) {
+ // NOTE: always call `done()` here to close
+ // the connection to the database
+ done();
+
+ return callback(err, result && result.rowCount > 0);
+ });
+ });
+}
+```
+
+### SQL Server
+
+```
+function verify (email, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+ const sqlserver = require('tedious@1.11.0');
+
+ const Connection = sqlserver.Connection;
+ const Request = sqlserver.Request;
+ const TYPES = sqlserver.TYPES;
+
+ const connection = new Connection({
+ userName: 'test',
+ password: 'test',
+ server: 'localhost',
+ options: {
+ database: 'mydb'
+ }
+ });
+
+ const query = 'UPDATE dbo.Users SET Email_Verified = true WHERE Email_Verified = false AND Email = @Email';
+
+ connection.on('debug', function(text) {
+ console.log(text);
+ }).on('errorMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) return callback(err);
+
+ const request = new Request(query, function (err, rows) {
+ if (err) return callback(err);
+ callback(null, rows > 0);
+ });
+
+ request.addParameter('Email', TYPES.VarChar, email);
+
+ connection.execSql(request);
+ });
+}
+```
+
+### Windows Azure SQL Database
+
+```
+function verify (email, callback) {
+ //this example uses the "tedious" library
+ //more info here: http://pekim.github.io/tedious/index.html
+
+ var Connection = require('tedious@1.11.0').Connection;
+ var Request = require('tedious@1.11.0').Request;
+ var TYPES = require('tedious@1.11.0').TYPES;
+
+ var connection = new Connection({
+ userName: 'your-user@your-server-id.database.windows.net',
+ password: 'the-password',
+ server: 'your-server-id.database.windows.net',
+ options: {
+ database: 'mydb',
+ encrypt: true
+ }
+ });
+
+ var query =
+ 'UPDATE Users SET Email_Verified=\'TRUE\' ' +
+ 'WHERE Email_Verified=\'FALSE\' AND Email=@Email';
+
+ connection.on('debug', function(text) {
+ // Uncomment next line in order to enable debugging messages
+ // console.log(text);
+ }).on('errorMessage', function(text) {
+ console.log(JSON.stringify(text, null, 2));
+ }).on('infoMessage', function(text) {
+ // Uncomment next line in order to enable information messages
+ // console.log(JSON.stringify(text, null, 2));
+ });
+
+ connection.on('connect', function (err) {
+ if (err) { return callback(err); }
+
+ var request = new Request(query, function (err, rows) {
+ if (err) { return callback(err); }
+ console.log('rows: ' + rows);
+ callback(null, rows > 0);
+ });
+
+ request.addParameter('Email', TYPES.VarChar, email);
+
+ connection.execSql(request);
+ });
+}
+
+```
+
+### Request with Basic Auth
+
+```
+function verify(email, callback) {
+ const request = require('request');
+
+ request.put({
+ url: 'https://myserviceurl.com/users',
+ json: { email: email }
+ //for more options check:
+ //https://github.com/mikeal/request#requestoptions-callback
+ }, function(err, response, body) {
+ if (err) return callback(err);
+ if (response.statusCode === 401) return callback();
+
+ callback(null, body);
+ });
+}
+```
+
+## Keep reading
+
+* [Change Passwords](/connections/database/custom-db/templates/change-password)
+* [Create](/connections/database/custom-db/templates/create)
+* [Delete](/connections/database/custom-db/templates/delete)
+* [Get User](/connections/database/custom-db/templates/get-user)
+* [Login](/connections/database/custom-db/templates/login)
+* [Change Email](/connections/database/custom-db/templates/change-email)
diff --git a/articles/connections/database/db2-script.md b/articles/connections/database/db2-script.md
index d9c9e1d728..17fb5c54c2 100644
--- a/articles/connections/database/db2-script.md
+++ b/articles/connections/database/db2-script.md
@@ -1,6 +1,13 @@
---
title: Login Script for IBM DB2
description: A custom callback script for those integrating with IBM DB2
+topics:
+ - connections
+ - custom-database
+ - ibm-db2
+contentType: reference
+useCase:
+ - customize-connections
---
# Login Script for IBM DB2
@@ -10,6 +17,7 @@ If you are integrating Auth0 with [IBM DB2](https://www.ibm.com/analytics/us/en/
```js
function login (email, password, callback) {
var ibmdb = require("ibm_db");
+ var bcrypt = require('bcrypt');
var credentials = "";
credentials += "DRIVER={DB2};";
diff --git a/articles/connections/database/index.md b/articles/connections/database/index.md
index 7b6a641f07..b83c31045f 100644
--- a/articles/connections/database/index.md
+++ b/articles/connections/database/index.md
@@ -2,22 +2,31 @@
description: How to create and use a database connection using either the Auth0 user store or your own user store.
crews: crew-2
url: /connections/database
+topics:
+ - connections
+ - database
+ - db-connections
+contentType:
+ - index
+ - concept
+useCase:
+ - customize-connections
---
-# Database Identity Providers
+# Database Connections
Auth0 provides database connections to authenticate users with an email/username and password. These credentials are securely stored in the Auth0 user store or in your own database.
-You can create a new database connection and manage existing ones in the [Dashboard](${manage_url}/#/connections/database):
+You can create a new database connection and manage existing ones at [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database):
-
+
## Scenarios
Typical database connection scenarios include:
* [Using the Auth0 user store](#using-the-auth0-user-store)
-* [Using your own user store](#using-your-own-store)
+* [Using your own user store](#using-your-own-user-store)
* [Migrating to Auth0 from a custom user store](#migrating-to-auth0-from-a-custom-user-store)
* [Requiring a username for users](/connections/database/require-username)
@@ -28,29 +37,21 @@ Auth0 provides the database infrastructure to store your users by default. This
The Auth0-hosted database is highly secure. Passwords are never stored or logged in plain text but are hashed with **bcrypt**. Varying levels of password security requirements can also be enforced (see: [Password Strength in Auth0 Database Connections](/password-strength)).
::: note
-For database connections, Auth0 limits the number of repeat login attempts per user and IP address. For more information, see: [Rate Limits on User/Password Authentication](/connections/database/rate-limits).
+For database connections, Auth0 limits the number of repeat login attempts per user and IP address. For more information, see: [Rate Limits on User/Password Authentication](/policies/rate-limit-policy/database-connections-rate-limits).
:::
### Using your own user store
-If you have an existing user store, or wish to store user credentials on your own server, Auth0 enables you to connect to a database or repository and use it as the identity provider.
+If you have an existing user store, or wish to store user credentials on your own server, Auth0 enables you to connect to a [custom database](/connections/database/custom-db) or repository and use it as the identity provider.
-
+
-In this scenario, you provide the login script to authenticate the user that will execute each time a user attempts to log in. Optionally, you can create scripts for sign-up, email verification, password reset and delete user functionality.
+In this scenario, you provide the login script to authenticate the user that will execute each time a user attempts to log in. Optionally, you can create [scripts](/connections/database/custom-db/templates) for sign-up, email verification, password reset, and delete user functionality.
-These custom scripts are Node.js code that run in the tenant's [Webtask](https://webtask.io/) environment. Auth0 provides templates for most common databases, such as: **ASP.NET Membership Provider**, **MongoDB**, **MySQL**, **Oracle**, **PostgreSQL**, **SQL Server**, **Windows Azure SQL Database**, and for a web service accessed by **Basic Auth**. Essentially, you can connect to any kind of database or web service with a custom script.
+The scripts are Node.js code. Auth0 provides [templates](/connections/database/custom-db/templates) for most common databases, such as: **ASP.NET Membership Provider**, **MongoDB**, **MySQL**, **PostgreSQL**, **SQL Server**, **Windows Azure SQL Database**, and for a web service accessed by **Basic Auth**. Essentially, you can connect to almost any kind of database or web service with a custom script.
-When using your own user database or user store:
-
-* Latency will be greater compared to Auth0-hosted user stores
-* The database or service must be reachable from the Auth0 servers. You will need to configure inbound connections if your store is behind a firewall.
-* Database scripts run in the same [Webtask](https://webtask.io) container, which is shared with all other extensibility points (such as rules, webtasks or other databases) belonging to the same Auth0 domain. Therefore, you must carefully code for error handling and throttling.
-
-::: note
-Check out [Authenticate Users Using Your Database](/connections/database/custom-db) for instructions on how to set up your own user store as an identity provider for Auth0.
-:::
+<%= include('../../_includes/_webtask') %>
### Migrating to Auth0 from a custom user store
-In this scenario, you have a legacy user store and wish to switch to the Auth0 store. Auth0 provides an automatic migration feature that adds your users to the Auth0 database one-at-a-time as each logs in and avoids asking your users to reset their passwords all at the same time. For a detailed guide to this feature see [Automatic User Migration](/users/migrations/automatic).
+In this scenario, you have a legacy user store and wish to switch to the Auth0 store. Auth0 provides an automatic migration feature that adds your users to the Auth0 database one-at-a-time as each logs in and avoids asking your users to reset their passwords all at the same time. For more information, see [Configure Automatic User Migration](/users/guides/configure-automatic-migration).
diff --git a/articles/connections/database/password-change.md b/articles/connections/database/password-change.md
index dd95b3cd01..875101bd33 100644
--- a/articles/connections/database/password-change.md
+++ b/articles/connections/database/password-change.md
@@ -1,36 +1,47 @@
---
-title: Changing a User's Password
-description: This document explains the ways you can reset the passwords for users of your Auth0 applications.
-crews: crew-2
+description: Describes the different ways to reset the users' passwords for your Auth0 applications.
+toc: true
+topics:
+ - connections
+ - database
+ - db-connections
+ - passwords
+contentType: how-to
+useCase: customize-connections
---
-# Changing a User's Password
+# Change Users' Passwords
-:::panel-warning Notice
-This information applies to those using **Change Password flow v2**. If you are using the old **Change Password flow** or Lock 8, check the notice panels like this one for information on differences between the two flows.
+This topic describes different ways to reset the password for a user in your database. You can change passwords for users in your [database connections](/connections/database) only. Users signing in with [social](/connections/social) or [enterprise](/connections/enterprise) connections must reset their passwords with the identity provider (such as Google or Facebook).
-To determine the flow you are using, navigate to [Dashboard > Tenant Settings > Advanced](${manage_url}/#/tenant/advanced) to check if the **Change Password flow v2** toggle is enabled. If it is, use Lock 9+. If not, use an older version of Lock to trigger the old Change Password flow.
+There are two basic methods for changing a user's password:
-We strongly encourage you to enable **Change Password flow v2** and use the latest version of Lock. To learn more about the vulnerability and migration, please see [Vulnerable Password Flow](/migrations/past-migrations#vulnerable-password-flow). To learn more about migrating to Lock 11, please take a look at the [Lock 11 Migration Guide](/libraries/lock/v11/migration-guide).
+- [Trigger an interactive password reset flow](#trigger-an-interactive-password-reset-flow) that sends the user a link through email. The link opens the Auth0 password reset page where the user can enter a new password.
+- [Directly set the new password](#directly-set-the-new-password) using the Auth0 Management API or the Auth0 Dashboard.
+
+::: note
+Resetting a user's password makes their session expire.
:::
-You can change your users' passwords using one of the following methods.
+:::panel Not what you're looking for?
+- To configure the custom Password Reset page, read [Customize Hosted Password Reset Page](/universal-login/password-reset).
+- To implement custom behavior after a successful password change, read [Post Change Password Hook](/hooks/extensibility-points/post-change-password).
+- To reset the password to your personal Auth0 user account, read [Reset Your Auth0 Account Password](/support/reset-account-password).
+:::
-+ [**Authentication API**](#using-the-authentication-api): Send a `POST` call to the Authentication API to send a password reset email to the user.
-+ [**Management API**](#using-the-management-api): Send a `PATCH` call to the Management API to update the user's password manually.
-+ [**Lock**](#using-lock): Use the Lock login screen to trigger a password reset email to the user.
-+ [**Dashboard**](#manually-setting-a-user-s-password): Use the [Users](${manage_url}/#/users) section of the Dashboard to manually change the user's password.
-::: note
-You can only change passwords for users signing in using Database connections. Users signing in using Social or Enterprise connections need to reset their passwords with the appropriate system.
-:::
+## Trigger an interactive password reset flow
-## Using the Authentication API
+There are two ways to trigger an interactive password reset flow, depending on your use case: through the Universal Login page or the Authentication API.
-To reset a user's password using the Authentication API, make a `POST` call specifying the email address of the user account whose password you would like to reset in the `email` field. If the call is successful, the user will receive an email prompting them to change their password.
+### Universal Login Page
+If your application uses Universal Login, the user can use the Lock widget on the Login screen to trigger a password reset email. With the New Universal Login Experience, the user can click the **Don't remember your password?** link and then enter their email address. This fires off a POST request to Auth0 that triggers the password reset process. The user [receives a password reset email](#password-reset-emails).
-::: note
-If you're calling this from the browser, don't forget to add your URL to the the `Allowed Web Origins` list in the [Dashboard](${manage_url}/#/applications/${account.clientId}/settings).
-:::
+### Authentication API
+If your application uses an interactive password reset flow through the Authentication API, make a `POST` call. In the `email` field, provide the email address of the user who needs to change their password. If the call is successful, the user [receives a password reset email](#password-reset-emails).
+
+If you call the API from the browser, be sure the origin URL is allowed: Go to [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications/${account.clientId}/settings) and add the URL to the `Allowed Origins (CORS)` list.
+
+If your connection a custom database, check to see if the user exists in the database before you invoke the Authentication API for `changePassword`.
```har
{
@@ -46,32 +57,42 @@ If you're calling this from the browser, don't forget to add your URL to the the
}
```
-:::panel-warning Custom Database
-If you have a custom database set up for your Connection and the user exists in the database, invoke the Authentication API for `changePassword`.
-:::
+### Password reset email
-If the `POST` call is successful, the user will receive an email containing a link to reset their password.
+Regardless of how the password reset process was triggered, the user receives email containing a link to reset their password.
-
+
-Clicking the link will send the user to a password reset page.
+Clicking the link sends the user to the [password reset page](/universal-login/password-reset).
-
+After submitting the new password, the user sees confirmation that they can now log in with their new credentials.
-::: note
-The reset password link in the email is valid for one use only, and it must be used before the time specified in the `URL Lifetime` field elapses. The `URL Lifetime` field can be modified in the Dashboard where you customize the Change Password email.
-:::
+Notes on password resets:
+- The reset password link in the email is valid for one use only.
+- If the user receives multiple password reset emails, only the password link in the most recent email is valid.
+- The `URL Lifetime` field determines how long the link is valid. From the Auth0 dashboard, you can [customize the Change Password email](/email/templates) and modify the link's [lifetime](/api/authentication/reference#change-password).
-Please see the [Change User Password for DB Connections](/api/authentication/reference#change-password) Authentication API endpoint for more information.
+In the [Classic Universal Login Experience](/universal-login/classic) you can [configure a url](/email/templates#configuring-the-redirect-to-url) to redirect users after completing the password reset. The URL receives a success indicator and a message.
-## Using the Management API
+The [New Experience](/universal-login/new) redirects the user to the [default login route](/universal-login/default-login-url) when it succeeds, and handles the error cases as part of the Universal Login flow. This experience ignores the Redirect URL in the email template.
-To reset a user's password using the Management API, make a `PATCH` call to the [Update a User endpoint](/api/management/v2#!/Users/patch_users_by_id).
+::: panel Generate Password Reset Tickets
-::: warning
-Users will not receive notification that their password has been manually changed.
+The Management API v2 provides an additional endpoint, [Generate a password reset ticket]( /api/management/v2#!/Tickets/post_password_change), that generates a URL like the one in the password reset email. You can use the generated URL when the email delivery method is not appropriate. Keep in mind that in the default flow, the email delivery verifies the identity of the user. (An impostor wouldn't have access to the email inbox.) If you use the ticket URL, your application is responsible for verifying the identity of the user in some other way.
:::
+## Directly set the new password
+
+To set a new password directly for the user without sending a password reset email, use either the [**Management API**](#using-the-management-api) or the [**Auth0 Dashboard**](#manually-set-users-passwords-using-the-dashboard).
+
+::: note
+Users do not receive notification when you change their password.
+:::
+
+### Use the Management API
+
+If you want to implement your own password reset flow, you can directly change a user's password from a server request to the Management API: make a `PATCH` call to the [Update a User endpoint](/api/management/v2#!/Users/patch_users_by_id).
+
```har
{
"method": "PATCH",
@@ -87,57 +108,12 @@ Users will not receive notification that their password has been manually change
}
```
-## Using Lock
-
-Users can change their passwords using the Lock screen.
-
-To begin the password change process, the user would click on the **Don't remember your password?** link on the Lock screen:
-
-
-
-They would then enter their email address:
+### Manually set users' passwords using the Auth0 Dashboard
-
+Anyone with administrative privileges to your Auth0 tenant can manually change a user's password at [Auth0 Dashboard > User Management > Users](${manage_url}/#/users).
-:::panel-warning Notice
-If you are using Lock version 8, the user will be asked, immediately after clicking the **Don't remember your password?** link on the Lock screen, to provide their email address and their new password. The user would then confirm this action via email.
-
-However, this flow is not considered safe. We recommend that you upgrade to Lock 9 or later to utilize a more secure flow. To learn more about migrating Lock, see [Vulnerable Password Flow](/migrations/past-migrations#vulnerable-password-flow).
-:::
-
-The user will then receive an email containing a link to reset the password:
-
-
-
-Clicking the link will send the user to a password reset page where they can enter their new password:
-
-
-
-After submitting the new password, the user will be able to login with their new credentials:
-
-
-
-## Manually Setting a User's Password
-
-::: warning
-Users will not receive notification that their password has been manually changed.
-:::
-
-You, or anyone with administrative privileges to your Auth0 tenant, can manually change a user's password in the [Users](${manage_url}/#/users) section of the Dashboard.
-
-Click on the name of the user for whom you want to change the password. Then, click on the **Actions** button on the right side of the page, and select **Change Password**.
-
-
-
-Enter the new password and click **Save**.
-
-
-## Customizing the Change Password Email
-
-You can change the content of the Change Password emails in the [Emails > Templates](${manage_url}/#/emails) section of the Dashboard. Select the **Change Password** template to edit the email fields:
-
-
-
-::: note
-Email templates can only be changed for those *not* using Auth0's built-in email provider. For more information, please see: [Customizing Your Emails](/email/templates).
-:::
+1. Select the name of the user whose password you want to change.
+2. Locate the **Danger Zone** at the bottom of the page.
+3. In the red **Change Password** box, click **CHANGE**.
+ 
+3. Enter the new password and click **Save**.
diff --git a/articles/connections/database/password-options.md b/articles/connections/database/password-options.md
index d497f5ef5b..645302fc79 100644
--- a/articles/connections/database/password-options.md
+++ b/articles/connections/database/password-options.md
@@ -2,40 +2,43 @@
title: Password Options in Auth0 Database Connections
description: Auth0's Password Options allow you to disallow users from repeating prior passwords, to customize a password dictionary of passwords to disallow, and to disallow passwords related to the user's personal data.
crews: crew-2
+topics:
+ - connections
+ - database
+ - db-connections
+ - passwords
+contentType: concept
+useCase: customize-connections
---
# Password Options in Auth0 Database Connections
::: warning
-The **Password Options** feature is only available for Database connections. The password limitations in Social and Enterprise connections are enforced by each provider.
+**Password History**, **Password Dictionary**, and **Personal Data** password options are available for Database connections using the Auth0 data store and for Custom Database connections that have import mode enabled. Password limitations in Social and Enterprise connections are enforced by each provider.
:::
-An important concern when using passwords for authentication is the creation of unique passwords. A strong password policy will make it difficult, if not improbable, for someone to guess a password through either manual or automated means.
+When using passwords for authentication, you should enforce the creation of unique passwords. A strong password policy will make it difficult, if not improbable, for a bad actor to guess a password through either manual or automated means.
-One facet of strong passwords is their uniqueness and difficulty to guess. Auth0's password options for database connections are designed to allow you to force your users to make better decisions when choosing their passwords.
+Important facets of strong passwords are their uniqueness and difficulty to guess. Auth0's password options for database connections allow you to force your users to make better decisions when choosing their passwords.
-
+
-The Password Options area is located in your [Auth0 Dashboard](${manage_url}). Go to Connections -> Database, choose a database connection, and then open its settings, and click _Password Policy_. The Password Policy settings page contains the ability to configure the [Password Strength Policy](/connections/database/password-strength) as well as the Password Options below.
+The Password Options area is located at [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database). Choose a database connection, then select the **Password Policy** view. The Password Policy settings page contains the ability to configure the [Password Strength Policy](/connections/database/password-strength) as well as the following Password Options.
## Password History
-When your users are creating passwords, you often don't want them to repeat the usage of passwords that they've used in the recent past. That, of course, would defeat the purpose of having them change their password! Even if you do not have a required password change policy (for example, forcing users to change passwords every six months), you still might have a reason to disallow the use of previous passwords. For example, if a security breach in your organization causes you to want users to change their passwords everywhere, you want to ensure that they aren't just re-using one that might be compromised!
+Enabling this option disallows users from setting passwords that repeat passwords they've used in the recent past. Auth0 can retain a password history for each user, up to a maximum of 24 entries per user. Note that when this option is enabled, only password changes going forward will be affected because the history will not have been kept prior to that point.
-Auth0 can retain a password history for each user in order to prevent their re-use. You can choose an amount of prior password entries to keep, up to 24 maximum.
-
-Note that upon enabling this option, only password changes going forward will be affected, as the history will not have been kept until that point.
+Even if you do not have a required password change policy (for example, forcing users to change passwords every six months), you still may want to disallow the use of previous passwords. For example, if a security breach in your organization causes you to force users to change their passwords everywhere, you will want to ensure they aren't just re-using passwords that might be compromised.
## Password Dictionary
-The Password Dictionary option, when enabled, allows the use of a password dictionary to stop users from choosing common passwords. The [default dictionary list](https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10k-most-common.txt) that Auth0 uses can be enabled just by toggling this option on. It will not allow users to use a password that is present on that list.
-
-Additionally, you can use the text area here and add your own prohibited passwords, one per line. These can be items that are specific to your company, or passwords that your own research has shown you are commonly used in general or at your company in specific.
+Enabling this option disallows users from setting passwords to common options included in a [default dictionary list](https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10k-most-common.txt). You may also include your own prohibited passwords by entering them in the text field in this section.
Note that Auth0 uses case-insensitive comparison with the Password Dictionary feature.
## Personal Data
-Enabling this option will force a user that is setting their password to not set passwords that contain any part of the user's personal data. This includes:
+Enabling this option disallows users from setting passwords that contain any part of their personal data. This includes:
* `name`
* `username`
@@ -45,13 +48,13 @@ Enabling this option will force a user that is setting their password to not set
* `user_metadata.last`
* The first part of the user's email will also be checked - `firstpart`@example.com
-For example, if the user's name is "John", including "John" in the user's password `John1234` would not be allowed, if this option is enabled.
+For example, if the user's name were "John", the user would not be allowed to include "John" in their password; `John1234` would not be allowed.
## API Access
-Password options are associated with a Database connection so these values can be accessed with the [Connections endpoints of the Management API](/api/management/v2#!/Connections). The password related fields are stored in the `options` object. These fields are not required because these fields are not used for non-database connections and if they are not enabled for a connection they may not appear.
+Because password options are associated with a Database connection, you can access them using the [Connections endpoints of the Management API](/api/management/v2#!/Connections). Password-related fields are stored in the `options` object. Because these fields are not used for non-database connections, they are not required, so if they are not enabled for a connection, they may not appear.
-For example here is what a MySQL database connection may look like after setting a password policy. In this example, as we can see from the contents of the `options` object, all three password options are enabled, password history will store the 5 latest passwords and each password will be crossed checked against two dictionaries: `entry1` and `entry2`.
+For example, after setting a password policy, a MySQL database connection will look like this:
```json
{
@@ -82,4 +85,6 @@ For example here is what a MySQL database connection may look like after setting
}
```
-If you are [creating a connection](/api/management/v2#!/Connections/post_connections) or [updating an existing connection](/api/management/v2#!/Connections/patch_connections_by_id) using the Management API you can update the password policy for the connection using these fields.
+In this example, we can see from the `options` object that all three password options are enabled, password history will store the 5 most recent passwords, and each password will be cross-checked against two dictionaries: `entry1` and `entry2`.
+
+If you are [creating a connection](/api/management/v2#!/Connections/post_connections) or [updating an existing connection](/api/management/v2#!/Connections/patch_connections_by_id) using the Management API, you can update the password policy for the connection using these fields.
diff --git a/articles/connections/database/password-strength.md b/articles/connections/database/password-strength.md
index dbd22b1aee..fe9d4a414b 100644
--- a/articles/connections/database/password-strength.md
+++ b/articles/connections/database/password-strength.md
@@ -1,7 +1,13 @@
---
title: Password Strength in Auth0 Database Connections
description: Auth0's Password Strength feature allows you to customize the level of enforced complexity for passwords entered during user sign-up. Auth0 offers 5 levels of security to match OWASP password recommendations.
-crews: crew-2
+topics:
+ - connections
+ - database
+ - db-connections
+ - passwords
+contentType: concept
+useCase: customize-connections
---
# Password Strength in Auth0 Database Connections
@@ -19,22 +25,99 @@ The following characteristics define a strong password:
## Password policies
-Auth0's Password Strength feature allows you to customize the level of enforced complexity for passwords entered during user sign-up. Auth0 offers 5 levels of security to match [OWASP password recommendations](https://www.owasp.org/index.php/Authentication_Cheat_Sheet#Implement_Proper_Password_Strength_Controls).
+Auth0's Password Strength feature allows you to customize the level of enforced complexity for passwords entered during user sign-up. Auth0 offers 5 levels of security to match [OWASP password recommendations](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Authentication_Cheat_Sheet.md).
At each level, new passwords must meet the following criteria:
- * **None** (default): at least 1 character of any type.
- * **Low**: at least 6 characters.
- * **Fair**: at least 8 characters including a lower-case letter, an upper-case letter, and a number.
- * **Good**: at least 8 characters including at least 3 of the following 4 types of characters: a lower-case letter, an upper-case letter, a number, a special character (such as !@#$%^&*).
- * **Excellent**: at least 10 characters including at least 3 of the following 4 types of characters: a lower-case letter, an upper-case letter, a number, a special character (such as `!@#$%^&*`). Not more than 2 identical characters in a row (such as `111` is not allowed).
+* **None** (default): at least 1 character of any type.
+* **Low**: at least 6 characters.
+* **Fair**: at least 8 characters including a lower-case letter, an upper-case letter, and a number.
+* **Good**: at least 8 characters including at least 3 of the following 4 types of characters: a lower-case letter, an upper-case letter, a number, a special character (such as !@#$%^&*).
+* **Excellent**: at least 10 characters including at least 3 of the following 4 types of characters: a lower-case letter, an upper-case letter, a number, a special character (such as `!@#$%^&*`). Not more than 2 identical characters in a row (such as `111` is not allowed).
+::: note
+The password policy for Auth0 Dashboard Admins will mirror the criteria set for the **Fair** level.
+:::
-## Change Your Policy
+## Minimum password length
+
+You can set a minimum length requirement for passwords that is independent of the policy strength requirements described in the [section immediately above](#password-policies).
+
+The minimum password length you can set is **1 byte**, while the maximum is **72 bytes**.
+::: note
+The maximum limit may vary depending on the password hashing algorithm you use.
+:::
+
+If you opt for a higher-level password policy, but you do not specify a minimum length value, the minimum password length for the policy level will automatically be used:
+
+| Password Policy Level | Minimum Password Length |
+| - | - |
+| None | 1 |
+| Low | 6 |
+| Fair | 8 |
+| Good | 8 |
+| Excellent | 10 |
-To change the password strength policy, go to [Database connections](${manage_url}/#/connections/database). Select the database connection you want to change and click on the **Password Strength** tab:
+If you provide a minimum password length, this value supercedes that indicated by the password policy.
-
+### Minimum password length when using Universal Login Pages
+
+If you are using either the [Universal Login Page](/universal-login) or the [Universal Login Password Reset Page](/universal-login/password-reset), and you want to set the minimum password length value, you will need to complete a few additional configuration steps using the [Auth0 Dashboard](${manage_url}).
+
+#### Set minimum password length when using Hosted Password Reset Pages
+
+If you're using a customized [Password Reset Page](/universal-login/password-reset) and you want to set the password length parameter, you must:
+
+1. Update your templates to include library version 1.5.1 or later
+2. Add `password_complexity_options` to leverage the new parameter
+
+If you do not [update the Password Reset Page](/universal-login/password-reset#edit-the-password-reset-page), Auth0 ignores any attempt to set the minimum password length.
+
+##### Step 1: Update the change password library version
+
+To use the new minimum password length feature, you should update the change password library used to version 1.5.1 (or later):
+
+```text
+
+```
+
+##### Step 2: Add `password_complexity_options` to leverage the new parameter
+
+You'll need to add `password_complexity_options` to leverage the new parameter. Add this option to the page's script as follows:
+
+```text
+
+```
+
+Scroll to the bottom and click **Save**.
+
+#### Set minimum password length when using Universal Login Pages
+
+If you're using a customized [Login Page](/universal-login) and you want to set the password length parameter, you must [update the page to use Lock version 11.9 or later](/universal-login/classic).
+
+```text
+
+```
+
+Scroll to the bottom and click **Save**.
+
+## Change Your Policy
+
+To change the password strength policy, navigate to [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database). Select the database connection you want to change, select the **Password Policy** view, and locate the **Password Strength** section:
+
The new policy will be enforced on all subsequent user sign-ups and password changes. If the user enters a password that does not match the required criteria, the password will be rejected by Auth0 and the user will be asked to create one that complies with these requirements.
@@ -44,7 +127,7 @@ Existing passwords that were created prior to the change in policy will continue
### Lock
-After password policies have been enabled, users will be notified on sign-up and reset password Lock modes if their password does not meet the required criteria.
+After password policies have been enabled, users will be notified on sign-up and reset password Lock modes if their password does not meet the required criteria.
This is how Lock will appear on the desktop:
@@ -54,13 +137,18 @@ and on mobile:

-## Custom Signup Errors
+
+::: note
+If Auth0 rejects a provided password, the notification will display in English. If you would like to display notifications in another language, you will need to do so via client-side translation.
+:::
+
+## Custom signup errors
Sign-up errors will return a 400 HTTP status code. The JSON response will contain `code: invalid_password` when the password does not meet the selected password policy criteria.
The response will also contain additional information that can be used to guide the user to what is incorrect in the selected password:
-* A `message` is ready to be formated using the `printf` function (or Node.js `util.format`).
+* A `message` is ready to be formatted using the `printf` function (or Node.js `util.format`).
* `format` is an array with values to be used in the `message`. (`message` is separate from the `format` to allow easier i18n of error messages in custom UIs.)
* `verified` can be either `true` or `false`. Returns `false` if the rule has been violated.
@@ -106,6 +194,6 @@ This is a sample `description` error report from a `good` policy with `hello1234
}
```
-## Password Options
+## Password options
In addition to the Password Strength feature explained here, the Password Policy settings for a database connection also include various Password Options that can further enhance your connection's password policy and ensure that your users have more secure passwords. Take a look at the [Password Options](/connections/database/password-options) documentation for more information.
diff --git a/articles/connections/database/rate-limits.md b/articles/connections/database/rate-limits.md
deleted file mode 100644
index 207e77b5ee..0000000000
--- a/articles/connections/database/rate-limits.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: Rate Limits on User/Password Authentication
-description: Explains the Auth0 limits the number of repeat login attempts per user and IP address on database connections.
----
-
-# Rate Limits on User/Password Authentication
-
-For database connections Auth0 limits certain types of repeat login attempts depending on the user account and IP address, some of these limits are set as part of [Anomaly Detection](/anomaly-detection):
-
- - If a user enters their password incorrectly more than 10 times from a single IP address, they will be blocked from logging into that account from that IP address. Auth0 will send an email containing a link to unblock the user to the owner of the database account. This the [Brute Force Protection](/anomaly-detection#brute-force-protection) shield as part of Auth0's Anomaly Detection.
-
- - Depending on if the [2nd Level Brute Force Protection](/anomaly-detection#2nd-level-brute-force-protection) shield is enabled, users may also be blocked they attempt 100 failed login attempts from a single IP address using different usernames and incorrect passwords in 24 hours. This shield also blocks 50 sign up attempts per minute from the same IP address.
-
- - A user cannot login more than 5 times per minute as the same user from the same location, regardless of having the correct credentials. This limit does not apply if the frequent requests are from different users.
-
-## Unblocking a User
-
- The user account can be unblocked for a given IP address by the database owner following the unblock-user link or by the user properly completing a password reset procedure.
-
- [Click here to learn more about Blocking and Unblocking a User](/user-profile#blocking-and-unblocking-a-user)
-
-## Why are some successful login attempts blocked?
-
-To protect the health of the system overall, putting these restrictions in place help mitigate the load on our systems. Due to the high amount of customization Auth0 provides, we risk degradation of service from users that may perform high load stress or benchmark tests, as well as the possibility of bad code causing users to login multiple times.
-
-[Click here to learn more about API Rate Limits](/rate-limits)
diff --git a/articles/connections/database/require-username.md b/articles/connections/database/require-username.md
index 9352b39641..853dd26a08 100644
--- a/articles/connections/database/require-username.md
+++ b/articles/connections/database/require-username.md
@@ -2,43 +2,56 @@
title: Adding Username for Database Connections
description: How to add a username field for login to database connections.
crews: crew-2
+topics:
+ - connections
+ - database
+ - db-connections
+contentType: how-to
+useCase: customize-connections
---
# Adding Username for Database Connections
For database connections, you can have your users sign in with a username instead of their email address.
-## Require a username
+## Require username
-1. Go to the [Connections > Database](${manage_url}/#/connections/database) section of the dashboard.
+1. Go to the [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database), and select the name of the connection you want to edit.
-1. Select the connection you wish to edit by clicking on the connection name or the Settings gear icon.
-
+
-1. Under **Settings**, you will see **Requires Username**, use the toggle here to enable/disable requiring a username.
+2. Locate **Requires Username**, and use the toggle to enable or disable requiring a username.
-
+
-You can see how the this will affect the login screen by clicking on **Try Connection**. You can see that once **Requires Username** is enabled, new users will have to enter a username and their email address to sign up.
+To see how this will affect the login screen, select the **Try Connection** view. Notice that once **Requires Username** is enabled, new users must enter a username and their email address to sign up.
-
+
-Users can then login with either their username or their email address. For users who registered while **Requires Username** was disabled, there will be no Username field stored for them and they will have to login with their email.
+Users can then login with either their username or their email address. Users who registered while **Requires Username** was disabled will not have a Username field stored and will have to log in with their email address.
-### Username Length
+### Username length
-The default allowed length for usernames is between 1 and 15 characters. However, using the dashboard or via API v2, you can modify the length minimum and maximum (up to a maximum length of 128 characters).
+The default allowed length for usernames is between 1 and 15 characters. However, using the Auth0 Dashboard or via the Management API v2, you can modify the length minimum and maximum (up to a maximum length of 128 characters).
-
+
-### Allowed Characters
+### Allowed characters
The username field accepts the following characters:
-* Alphanumeric characters (without accent marks);
-* The underscore (_) character;
-* The plus (+) character;
-* The minus (-) character;
+* Alphanumeric characters (without accent marks, automatically converted to lowercase);
+* The at sign (@) character (but email addresses are not allowed);
+* The caret (^) character;
+* The dollar sign ($) character;
* The dot (.) character;
+* The exclamation (!) character;
+* The grave accent (\`) character;
+* The minus (-) character;
+* The number sign (#) character;
+* The plus (+) character;
+* The single quote (') character;
+* The tilde (~) character;
+* The underscore (_) character;
No other characters/symbols are allowed.
diff --git a/articles/connections/enterprise/_login-experience-tab.md b/articles/connections/enterprise/_login-experience-tab.md
new file mode 100644
index 0000000000..3158282d4d
--- /dev/null
+++ b/articles/connections/enterprise/_login-experience-tab.md
@@ -0,0 +1,9 @@
+| Field | Description|
+| -- | -- |
+| **Identity Provider domains** | A comma-separated list of the domains that can be authenticated in the Identify Provider. This is only applicable when using [Identifier First](/universal-login/identifier-first) authentication in the Universal Login Experience. |
+| **Add button** (Optional) | Display a button for this connection in the login page. |
+| **Button display name** (Optional) | Text used to customize the login button for new Universal Login. When set the button reads: "Continue with {Button display name}". |
+| **Button logo URL** (Optional) | URL of image used to customize the login button for new Universal Login. When set, the Universal Login login button displays the image as a 20px by 20px square. |
+::: note
+Optional fields are available with the New Login Experience only. Customers using the Classic experience will not see the Add button, Button display name, or Button logo URL.
+:::
diff --git a/articles/connections/enterprise/active-directory-ldap.md b/articles/connections/enterprise/active-directory-ldap.md
new file mode 100644
index 0000000000..c6cdc69026
--- /dev/null
+++ b/articles/connections/enterprise/active-directory-ldap.md
@@ -0,0 +1,103 @@
+---
+title: Connect Your App to Active Directory using LDAP
+connection: Active Directory / LDAP
+image: /media/connections/ad.png
+public: true
+alias:
+ - ad
+ - ldap
+seo_alias: active-directory
+description: Learn how to connect your app to Active Directory (AD) using Lightweight Directory Access Protocol (LDAP) through an enterprise connection.
+crews: crew-2
+topics:
+ - connections
+ - enterprise
+ - azure
+ - active-directory
+ - microsoft
+ - ldap
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+
+# Connect Your App to Active Directory using LDAP
+
+Auth0 integrates with Active Directory (AD) using Lightweight Directory Access Protocol (LDAP) through an **Active Directory/LDAP Connector** that you install on your network.
+
+The **AD/LDAP Connector** (1), is a bridge between your **Active Directory/LDAP** (2) and the **Auth0 Service** (3). This bridge is necessary because AD/LDAP is typically restricted to your internal network, and Auth0 is a cloud service running in a completely different context.
+
+
+
+For [high availability and load balancing](/connector/high-availability), you can install multiple instances of the connector. All connections are outbound from the connector to the Auth0 Server, so changes to your firewall are generally unnecessary.
+
+::: warning
+The AD/LDAP Connector is designed for scenarios where your company controls the AD/LDAP server. The connector should not be installed on your customer's servers.
+
+For B2B scenarios where you want to allow your customer's users to access your applications using their enterprise credentials, connect to your customer's federation service (for example, their own Auth0 service, ADFS, or any SAML identity provider) using one of the available enterprise connections.
+
+If you install an AD/LDAP connector on your customer's servers and it is connected directly to your Auth0 domain, you will have to handle the passwords of your customer's users directly. Auth0 strongly recommends against these types of deployments and does not support them.
+:::
+
+## Prerequisites
+
+**Before beginning:**
+
+* [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
+
+## Steps
+
+To connect your application to Active Directory/LDAP, you must:
+
+1. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0) and download the installer.
+2. [Install the connector on your network](#install-the-connector-on-your-network).
+3. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+4. [Test the connection](#test-the-connection).
+
+## Create an enterprise connection in Auth0
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **Active Directory / LDAP**, and select its `+`.
+
+ 
+
+2. Enter details for your connection, and select **Create**:
+
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **Display name** (optional) | Text used to customize the login button for Universal Login. When set, the Universal Login login button reads: "Continue with {Display name}". |
+| **Logo URL** (optional) | URL of image used to customize the login button for Universal Login. When set, the Universal Login login button displays the image as a 20px by 20px square. |
+| **IdP Domains** (optional) | Comma-separated list of valid email domains that will be allowed to log in using this connection. Only needed if using the Lock login widget. |
+| **Disable cache** | When enabled, disables caching. |
+| **Use client SSL certificate authentication** | When enabled, uses client SSL certificate authentication. |
+| **Use Windows Integrated Auth (Kerberos)** | When enabled, you will be asked to enter a range of IP addresses. When users log in through these IP addresses, Kerberos will be used; otherwise, AD/LDAP username/password will be requested. Typically, the IP range entered represent intranet addresses. |
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
+
+
+
+3. Download the provided installer and make note of the provided **Provisioning Ticket URL**.
+
+::: note
+We ship different versions of the connector to install on Windows or Linux platforms.
+:::
+
+## Install the connector on your network
+
+Set up the [AD/LDAP Connector](/connector) by following the instructions for your platform:
+
+- [Install the AD/LDAP Connector on Windows](/connector/install)
+- [Install the AD/LDAP Connector on Non-Microsoft Platforms](/connector/install-other-platforms)
+
+## Enable the enterprise connection for your Auth0 application
+
+To use your new AD connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
+
+## Test the connection
+
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
+
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/enterprise/active-directory.md b/articles/connections/enterprise/active-directory.md
deleted file mode 100644
index a5d827a55e..0000000000
--- a/articles/connections/enterprise/active-directory.md
+++ /dev/null
@@ -1,57 +0,0 @@
----
-title: Connect your app to Active Directory
-connection: Active Directory
-image: /media/connections/ms.png
-alias:
- - ad
-seo_alias: active-directory
-description: How to connect to Active Directory with Auth0.
-crews: crew-2
----
-
-# Connect your app to Active Directory
-
-Auth0 integrates with Active Directory/LDAP through the **Active Directory/LDAP Connector** that you install on your network.
-
-The **AD/LDAP Connector** (1), is a bridge between your **Active Directory** (2) and the **Auth0 Service** (3). This bridge is necessary because AD is typically restricted to your internal network, and Auth0 is a cloud service running in a completely different context.
-
-
-
-For [high availability and load balancing](/connector/high-availability), you can install multiple instances of the connector. All connections are out-bound from the connector to the Auth0 Server, so changes to your firewall are generally unnecessary.
-
-Configuring an AD/LDAP connection in Auth0 requires two steps:
-
-1. Create an AD/LDAP Connection in Auth0 and download the installer.
-2. Install the connector on your network.
-
-## Create an AD/LDAP Connection in Auth0
-
-These are the steps to connect your application. If you are looking to manage authentication in your application, see [Next Steps](#next-steps) below.
-
-Select **Connections > Enterprise > AD/LDAP** from the Auth0 dashboard menu. Click the **+ CREATE NEW CONNECTION** button and name the connection.
-
-
-
-In the *Email domains* field, list the user email domains that will be allowed to login to this particular AD/LDAP connection.
-
-If you want to use **Kerberos** with this connection, enter a range of IP addresses where **Kerberos** authentication will be enabled from. Typically, these would be intranet addresses.
-
-If you would like to disable caching, enable the appropriate slider.
-
-
-
-Click **Save**. You are done on the Auth0 side. Click the button on the next page to download the **AD/LDAP Connector** installer to your machine.
-
-
-
-::: note
-We ship different versions of the connector to install on Windows or Linux platforms.
-:::
-
-Keep the **TICKET URL** on hand as you will need it later.
-
-## Install the connector on your network
-
-Continue to the instructions on how to [Install the Connector](/connector).
-
-<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/enterprise/adfs.md b/articles/connections/enterprise/adfs.md
index f250faa48c..10b273635a 100644
--- a/articles/connections/enterprise/adfs.md
+++ b/articles/connections/enterprise/adfs.md
@@ -1,53 +1,64 @@
---
-title: Connect your app to ADFS
+title: Connect Your App to ADFS
connection: ADFS
-image: /media/connections/ms.png
+image: /media/connections/adfs.png
+public: true
alias:
- - active-directory-federation-services
- - adfs-2
+ - active-directory-federation-services
+ - adfs-2
seo_alias: adfs
-description: How to connect ADFS with Auth0.
+description: Learn how to connect your application to Active Directory Federation Services (ADFS) using enterprise connections.
crews: crew-2
+topics:
+ - connections
+ - enterprise
+ - azure
+ - active-directory
+ - microsoft
+ - ad-fs
+contentType: how-to
+toc: true
+useCase:
+ - customize-connections
+ - add-idp
+
---
-# Connect your app to ADFS
+# Connect Your App to ADFS
-First, provide this information to your ADFS administrator:
+To connect your application to Microsoft's Active Directory Federation Services (ADFS), you will need to provide the following information to your ADFS administrator:
* Realm Identifier: `urn:auth0:${account.tenant}`
-* Endpoint: `https://${account.namespace}/login/callback` (or, if you are using the [custom domains](/custom-domains) feature, `https:///login/callback`)
+* Endpoint: `https://${account.namespace}/login/callback` or `https:///login/callback`, if you are using a [custom domain](/custom-domains).
-::: note
-If you want to use the [/oauth/ro](/api/authentication/reference#resource-owner) endpoint you must enable `/adfs/services/trust/13/usernamemixed`.
-:::
-
-::: panel Federation Metadata
+::: panel Federated Metadata
The Federation Metadata file contains information about the ADFS server's certificates. If the Federation Metadata endpoint (`/FederationMetadata/2007-06/FederationMetadata.xml`) is enabled in ADFS, Auth0 can periodically (once a day) look for changes in the configuration, like a new signing certificate added to prepare for a rollover. Because of this, enabling the Federation Metadata endpoint is preferred to providing a standalone metadata file. If you provide a standalone metadata file, we will notify you via email when the certificates are close to their expiration date.
:::
+You can use a script to to setup the connection or set it up manually.
+
## Scripted setup
-For automated integration, this script uses the [ADFS PowerShell SnapIn](http://technet.microsoft.com/en-us/library/adfs2-powershell-basics.aspx) to create and configure a **Relying Party** that will issue, for the authenticated user, the following claims: **email**, **upn**, **given name** and **surname**.
+Run the following two commands in the Windows PowerShell window.
+
+::: note
+You must run this script as an administrator of your system.
+:::
```powershell
(new-object Net.WebClient -property @{Encoding = [Text.Encoding]::UTF8}).DownloadString("https://raw.github.com/auth0/adfs-auth0/master/adfs.ps1") | iex
-AddRelyingParty "urn:auth0:${account.tenant}" "https://${account.namespace}/login/callback"
```
-If you are using the [custom domains](/custom-domains) feature, you will need to replace the last URL in the above script with `https:///login/callback`.
-
-Copy and paste the script above into the Windows PowerShell window.
+```powershell
+AddRelyingParty "urn:auth0:${account.tenant}" "https://${account.namespace}/login/callback"
+```
-
+For automated integration, this script uses the [ADFS PowerShell SnapIn](http://technet.microsoft.com/en-us/library/adfs2-powershell-basics.aspx) to create and configure a **Relying Party** that will issue, for the authenticated user, the following claims: **email**, **upn**, **given name** and **surname**.
::: note
-You must run this script as an administrator of your system.
+If you are using the [custom domains](/custom-domains) feature, you will need to replace the `$webAppEndpoint` value with `https:///login/callback`.
:::
-### What the script does
-
-#### 1. Creates the Relying Party on ADFS
-
-The script creates the relying party on ADFS, as follows:
+The script creates the Relying Party Trust on ADFS, as follows:
```powershell
$realm = "urn:auth0:${account.tenant}";
@@ -58,11 +69,7 @@ Add-ADFSRelyingPartyTrust -Name $realm -Identifier $realm -WSFedEndpoint $webApp
$rp = Get-ADFSRelyingPartyTrust -Name $realm
```
-If you are using the [custom domains](/custom-domains) feature, you will need to replace the `$webAppEndpoint` value with `https:///login/callback`.
-
-#### 2. Creates rules to output common attributes
-
-The script also creates rules to output the most common attribures, such as email, UPN, given name, or surname:
+The script also creates rules to output the most common attributes, such as email, UPN, given name, or surname:
```powershell
$rules = @'
@@ -82,72 +89,71 @@ $rSet = New-ADFSClaimRuleSet –ClaimRule '=> issue(Type = "http://schemas.micro
Set-ADFSRelyingPartyTrust –TargetName $realm –IssuanceAuthorizationRules $rSet.ClaimRulesString
```
-## Manual setup
-
-If you don't feel comfortable executing the script, you can follow these manual steps:
+## Manual setup part 1: Add a Relying Party Trust
1. Open the ADFS Management Console.
-1. Click on **Add Relying Party Trust**.
-1. Click **Start** on the first step.
+1. On the right side of the console, click **Add Relying Party Trust**.
+1. Click **Start**.
1. Select **Enter data about the relying party manually** and click **Next**.
- 
-1. Enter an arbitrary name (such as "${account.appName}") and click **Next**.
-1. Leave the default selection (`ADFS 2.0 profile`) and click **Next**.
-1. Leave the default (`no encryption certificate`) and click **Next**.
-1. Check **Enable support for the WS-Federation...**, enter the following value in the textbox and click **Next**.
-
- `https://${account.namespace}/login/callback`
- 
+1. Type a name (such as `${account.appName}`) and click **Next**.
+1. Use the default (`ADFS 2.0 profile`) and click **Next**.
+1. Use the default (`no encryption certificate`) and click **Next**.
+1. Check **Enable support for the WS-Federation...** and type this value in the textbox:
- ::: note
- If you are using the [custom domains](/custom-domains) feature, use the following URL format instead: `https:///login/callback`.
- :::
+ `https://${account.namespace}/login/callback` or if you are using a [custom domain](/custom-domains), use `https:///login/callback`
-1. Add a *Relying party trust identifier* with the following value and click **Add** and then **Next**.
+1. Click **Next**.
+1. Add a Relying Party Trust identifier with this value:
`urn:auth0:${account.tenant}`
- 
-1. Leave the default option (*Permit all users...*) and click **Next**.
-1. Click **Next** and then **Close**. The UI will show a new window to edit the **Claim Rules**.
-1. Click on **Add Rule...**.
-1. Leave the default option (*Send LDAP Attributes as Claims*).
+1. Click **Add** and then **Next**.
+1. Leave the default `Permit all users...` and click **Next**.
+1. Click **Next** and then **Close**.
- 
+## Manual setup part 2: Add a claim issuance policy rule
-1. Give the rule an arbitrary name that describes what it does. For example:
+1. If you're using Windows Server 2019, the Edit Claim Issuance Polcy dialog box automatically opens when you finish the Add Relying Party Trust wizard. If you're using Windows 2012 or 2016, follow these steps:
+ | In Windows Server 2012 | In Windows Server 2016 |
+ | --- | --- |
+ | In the Actions panel on the right side of the console, find the Relying Party Trust you just created. Beneath it, click **Edit Claim Issuance Policy**. | In the console tree, under ADFS, click **Relying Party Trusts**. On the right side of the console, find the Relying Party Trust you just created. Right-click it and click **Edit Claim Issuance Policy**. |
- `Map ActiveDirectory attributes (mail -> Mail, displayName -> Name, userPrincipalName -> NameID, givenName -> GiveName, sn -> Surname)`
+2. In the Edit Claim Issuance Policy Window, under Issuance Transform Rules, click **Add Rule...**.
+3. Leave the default `Send LDAP Attributes as Claims`.
+4. Give the rule a name that describes what it does.
+5. Under Attribute Store, select **Active Directory**.
+6. Select these mappings under `Mapping of LDAP attributes to outgoing claim types` and click **Finish**.
-1. Select the mappings as shown in this image and click **Finish**.
+ | LDAP Attribute | Outgoing Claim Type |
+ | --- | --- |
+ | E-Mail-Addresses | E-Mail Address |
+ | Display-Name | Name |
+ | User-Principal-Name | Name ID |
+ | Given-Name | Given Name |
+ | Surname | Surname |
- 
+### Add additional LDAP attributes
-1. (Optional) Adding additional LDAP attributes
+The mappings in the previous steps are the most commonly used, but if you need additional LDAP attributes with information about the user, you can add more claim mappings.
- The mappings created on step **15** are the most commonly used, but if you need additional LDAP attributes with information about the user, you can add more claim mappings.
-
-::: note
-If you already closed the window on the previous step, select **Edit Claim Rules** on the context menu for the Relying Party Trust you created, and edit the rule from step **14**).
-:::
+1. If you closed the window on the previous step, select **Edit Claim Rules** on the context menu for the Relying Party Trust you created, and edit the rule.
-Create a row for every additional LDAP attribute you need, choosing the attribute name on the left column and desired claim type on the right column.
+2. Create an additional row for every LDAP attribute you need, choosing the attribute name in the left column and desired claim type in the right column.
-If the claim type you are looking for doesn't exist, you have two options:
+3. If the claim type you are looking for doesn't exist, you have two options:
-* Type a namespace-qualified name for the new claim (for example `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/department`).
-* Register a new claim type (under **AD FS | Services | Claim Descriptions**) on the ADFS admin console), and use the claim name in the mapping.
+ * Type a [namespace-qualified name](/tokens/guides/create-namespaced-custom-claims) for the new claim (for example `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/department`).
+ * Register a new claim type (under **ADFS > Services > Claim Descriptions**) on the ADFS admin console), and use the claim name in the mapping.
-Auth0 will use the name part of the claim type (for example `department` in `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/department`) as the attribute name for the user profile.
+ Auth0 uses the name part of the claim type (for example `department` in `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/department`) as the attribute name for the user profile.
## Next Steps
-Now that you have a working connection, the next step is to configure your application to use it. You can follow our step-by-step quickstarts or use directly our libraries and API.
+Now that you have a working connection, the next step is to configure your application to use it. You can follow our step-by-step quickstarts or use our libraries and API.
::: next-steps
* [Get started with our Quickstarts](/quickstarts)
* [Configure your application using our Lock login form](/libraries/lock)
* [Configure your application using our Auth0.js library and your own UI](/libraries/auth0js)
* [Use our Authentication API to authenticate](/api/authentication)
-* [Authenticate PHP with ADFS using Auth0](https://auth0.com/authenticate/php/adfs)
:::
diff --git a/articles/connections/enterprise/azure-active-directory-native.md b/articles/connections/enterprise/azure-active-directory-native.md
index 19f9a91f8c..142f690faa 100644
--- a/articles/connections/enterprise/azure-active-directory-native.md
+++ b/articles/connections/enterprise/azure-active-directory-native.md
@@ -1,7 +1,8 @@
---
-title: Native Azure Active Directory applications with Auth0
+title: Connect Your Native App to Microsoft Azure Active Directory Using Resource Owner Flow
connection: Azure Active Directory Native
image: /media/connections/azure.png
+public: true
alias:
- azure-ad-native-resource-owner
- waad-native-resource-owner
@@ -10,72 +11,172 @@ alias:
- microsoft-azure-ad-native-resource-owner
- microsoft-azure-active-directory-native-resource-owner
seo_alias: azure-active-directory-native
-description: How to setup native Azure Active Directory applications with Auth0 for a Resource Owner.
+description: Learn how to connect your app to Microsoft Azure Active Directory using an enterprise connection with the Resource Owner flow.
crews: crew-2
+topics:
+ - connections
+ - enterprise
+ - azure
+ - active-directory
+ - microsoft
+ - native-apps
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
+# Connect Your Native App to Microsoft Azure Active Directory Using Resource Owner Flow
-# Native Azure Active Directory applications with Auth0 (Resource Owner flow)
+In addition to the **WS-Federation** and **OpenID Connect** flows, it's also possible to use the **Resource Owner** flow with Azure AD. This flow allows you to capture and validate a user's credentials (email and password) instead of showing the Azure AD login page. For security and Single Sign-on (SSO) reasons, this is not the recommended approach; still, **Resource Owner** flow can be useful in Native mobile scenarios or to batch-process authentication with Azure AD.
-In addition to the **WS-Federation** and **OpenID Connect** flows, it's also possible to use the **Resource Owner** flow with Azure AD. This flow allows you to capture and validate a user's credentials (email and password) instead of showing the Azure AD login page. While this is not the recommended approach for security and SSO reasons, **Resource Owner** flow could be used in Native mobile scenarios or to batch process authentication with Azure AD.
+This configuration requires two applications: a *Web Application and/or Web API* and a *Native Client Application*. From Azure AD's point of view, users will be authenticated using the *Native Client Application* to gain access to the *Web Application and/or Web API*.
-This setup will require two applications, a *Web Application and/or Web API* and a *Native Client Application*. From Azure AD's point of view, users will be authenticated using the *Native Client Application* to gain access to the *Web Application and/or Web API*. If you are looking to manage authentication in your application, see [Next Steps](#next-steps) below.
+
-
+## Prerequisites
-## 1. Define a *Web Application and/or Web API* in Azure Active Directory
+**Before beginning:**
-The first step is to define the "Web Application and/or Web API".
+* [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an **Application Type** of **Native**.
+ * Add an **Allowed Callback URL**. Your callback URL format will vary depending on your platform. For details about the format for your platform, see our [Native Quickstarts](/quickstart/native).
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
-
+## Steps
-During setup, you'll need to specify the `App ID Uri` which will be needed later to configure the connection in Auth0.
+To connect your application using Resource Owner flow, you must:
-
+1. [Set up your applications in the Microsoft Azure portal](#set-up-your-applications-in-the-microsoft-azure-portal).
+2. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+3. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+4. [Test the connection](#test-the-connection).
-## 2. Define a *Native Client Application* in Azure Active Directory
+::: panel Microsoft Azure Account
+Before proceeding, you will need a valid Microsoft Azure account and must have **your own** Microsoft Azure AD directory for which you are a Global administrator.
-After creating the first application, you'll need to define a *Native Client Application*.
+If you don't have a Microsoft Azure account, you can [sign up](https://azure.microsoft.com/en-us/free) for free; then, if necessary, set up an Azure AD directory by following Microsoft's [Quickstart: Create a new tenant in Azure Active Directory - Create a new tenant for your organization](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-access-create-new-tenant#create-a-new-tenant-for-your-organization).
-
+Alternatively, if you have an Office 365 account, you can use the account's Azure AD instance instead of creating a new one. To access your Office 365 account's Azure AD instance:
-In this application, you'll need to configure the following permissions to other applications:
+1. [Sign in to Office 365](https://portal.office.com), and navigate to the [Office 365 Admin Center](https://portal.office.com/adminportal/home#/homepage).
+2. Open the **Admin centers** menu drawer located in the left menu, and click on **Azure AD**.
+:::
+
+## Set up your applications in the Microsoft Azure portal
+
+::: warning
+Before proceeding, you must have already set up **your own** Microsoft Azure AD directory for which you are a Global administrator. To learn how, follow Microsoft's [Quickstart: Create a new tenant in Azure Active Directory - Create a new tenant for your organization](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-access-create-new-tenant#create-a-new-tenant-for-your-organization).
+:::
+
+### Register a new web application
+
+To learn how to register your application with Azure AD, follow Microsoft's [Quickstart: Register an application with the Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) doc.
+
+::: warning
+If you have more than one Azure AD directory, make sure you are in the correct directory when you register your app.
+:::
+
+While setting up your app, make sure you use the following settings:
+
+* If you want to allow users from external organizations (like other Azure AD directories), then when asked to choose **Supported account types**, choose the appropriate multitenant option. Multitenant options include the following: **Accounts in any organizational directory (Any Azure AD directory - Multitenant)**.
+* When asked to set a **Redirect URI**, make sure `Web` is selected and enter your callback URL: `https://${account.namespace}/login/callback`.
+
+<%= include('../_find-auth0-domain-redirects.md') %>
+
+During this process, Microsoft will generate an **Application (client) ID** for your application; you can find this on the app's **Overview** screen. Make note of this value.
+
+### Configure your web application to expose an API
+
+To learn how to configure your **Web** application to expose an API with Azure AD, follow Microsoft's [Quickstart: Configure an application to expose web APIs](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis).
+
+While configuring your app, make sure you use the following settings:
+
+* When asked to set a **Scope name**, enter `API.Access`.
+
+During this process, Microsoft will generate an **Application ID URI**. Make note of this value.
- - **Windows Azure Active Directory**: *Read directory data* and *Enable sign-on and read users' profiles*
- - Your **Web Application and/or Web API**: *Access your API*
+### Register a new native application
-
+Again, follow Microsoft's [Quickstart: Register an application with the Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) doc.
-## 3. Configure the connection in Auth0
+::: warning
+If you have more than one Azure AD directory, make sure you are in the correct directory when you register your app.
+:::
-After creating both applications in Azure Active Directory, you can configure the Auth0 connection.
+While setting up your app, make sure you use the following settings:
-Login to your [Auth0 Dashboard](${manage_url}), and select the **Connections > Enterprise** menu option.
+* If you want to allow users from external organizations (like other Azure AD directories), then when asked to choose **Supported account types**, choose the appropriate multitenant option. Multitenant options include the following: **Accounts in any organizational directory (Any Azure AD directory - Multitenant)**.
+* When asked to set a **Redirect URI**, make sure `Public client/native (mobile & desktop)` is selected and enter your callback URL. Your callback URL format will vary depending on your platform. For details about the format for your platform, see our [Native Quickstarts](/quickstart/native).
-
+During this process, Microsoft will generate an **Application (client) ID** for your application; you can find this on the app's **Overview** screen. Make note of this value.
-Select **Microsoft Azure AD**. You will be asked to provide the appropriate settings, including data about the app registration you just created in Auth0.
+### Create a client secret for your native application
-
+To learn how to create a client secret, follow Microsoft's [Quickstart: Configure a client application to access web APIs - Add Credentials to your web application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application). You want to generate a **Client secret**. Once generated, make note of this value.
::: note
-The `App ID Uri` must be set to the Uri which was configured previously in the *Web Application and/or Web API* and the `Client ID` must be set to the `Client ID` of the *Native Client Application*. In this setup, the `Client Secret` does not matter and can be set to any value.
+If you configure an expiring secret, make sure to record the expiration date; you will need to renew the key before that day to avoid a service interruption.
:::
-## 4. Test the connection
+### Add permissions for your native application
+
+To learn how to add permissions for your **Native** application, follow Microsoft's [Quickstart: Configure a client application to access web APIs - Add permissions to access web APIs](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-permissions-to-access-web-apis). You want to configure permissions for the **Microsoft Graph API** and for the **Web** application you configured to expose an API.
+
+While setting up your permissions, make sure you use the following settings for **Microsoft Graph API**:
+
+* When asked for a permission type, choose **Delegated permissions**. Under **User**, select **User.Read** so your app can sign in users and read the signed-in user's profile. Under **Directory**, select **Directory.Read.All** so your app can read directory data on the signed-in user's behalf.
+
+For your **Web** app that you configured to expose an API, make sure you use the following settings:
+
+* When asked for a permission type, choose **Delegated permissions**. Under **API**, select **API.Access** so your app can access your API on the user's behalf.
+
+## Configure the connection in Auth0
+
+After creating both applications in Azure AD, you can configure the Auth0 connection.
+
+1. Navigate to the [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **Microsoft Azure AD**, and click its `+`.
-To test the complete setup, you can use the [Resource Owner endpoint](/api/authentication/reference#resource-owner). Enter the username and password of a user and choose the connection. Click **Try Me!** to sign in as that user.
+
-
+2. Enter details for your connection, and select **Create**:
+
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **Microsoft Azure AD Domain** | Your Azure AD domain name. You can find this on your Azure AD directory's overview page in the Microsoft Azure portal. |
+| **Client ID** | Unique identifier for your registered Azure AD application. Enter the saved value of the **Application (client) ID** for the **Native** application you registered in Azure AD. |
+| **Client Secret** | String used to gain access to your registered Azure AD application. Enter the saved value of the **Client secret** for the **Native** app you registered in Azure AD. |
+| **Use common endpoint** (optional) | When enabled, your application will dynamically accept users from new directories. Typically enabled if you selected a multitenant option for **Supported account types** for the application you registered in Azure AD. When enabled, Auth0 will redirect users to Azure's common login endpoint, and Azure will perform *Home Realm Discovery* based on the domain of the user's email address. |
+| **Identity API** | API used by Auth0 to interact with Azure AD endpoints. Learn about the differences in behavior in Microsoft's [Why update to Microsoft identity platform (v2.0)](https://docs.microsoft.com/en-us/azure/active-directory/develop/azure-ad-endpoint-comparison) doc. Select `Azure Active Directory (v1)`, and for **App ID URI**, enter the saved value of the **Application ID URI** that was created when you configured your **Web** application to expose an API. |
+| **Attributes** | Basic attributes for the signed-in user that your app can access. Indicates how much information you want stored in the Auth0 User Profile. |
+| **Extended Attributes** (optional) | Extended attributes for the signed-in user that your app can access. |
+| **Auth0 APIs** (optional) | When selected, indicates that you require the ability to make calls to the Azure AD Users API. |
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
+| **Email Verification** | Choose how Auth0 sets the `email_verified` field in the user profile. To learn more, see [Email Verification for Azure AD and ADFS](/connections/azuread-adfs-email-verification). |
+
+
+
+## Enable the enterprise connection for your Auth0 application
+
+To use your new Azure AD enterprise connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
+
+## Test the connection
+
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
## Group Memberships and Advanced Profile Information
-In this native flow Auth0 will receive an Access Token from Azure AD which has been issued for your **Web Application and/or Web API**. Because of that features like loading group memberships and advanced profile information will no longer work. This is because the Access Token received by Azure AD can no longer be used to query the Azure AD Graph API for this additional information.
+In this native flow, Auth0 will receive an Access Token from Azure AD which has been issued for your Azure AD **Web** application. As a result, features like loading group memberships and advanced profile information will no longer work because the Access Token received by Azure AD can no longer be used to query the Azure AD Graph API for this additional information.
+
+However, if you depend on group memberships and advanced profile information, you can change your configuration to accommodate your needs.
+
+1. Configure your **Native** application with additional permissions for the **Microsoft Graph API**:
-If you depend on group memberships and advanced profile information you can however change your configure. First you will need to configure the **Native** application with additional read permissions for Azure AD:
+ * When asked for a permission type, choose **Delegated permissions**. Under **Directory**, select **Directory.AccessAsUser.All**, so your app can access the directory as the signed-in user.
-
+2. In Auth0, modify your Azure AD enterprise connection as follows, then **Save Changes**:
-Then in Auth0 instead of specifying the `App ID Uri` of your "Web Application and/or Web API" you will need to use the Azure AD Graph API instead:
+ * In **Identity API**, select `Azure Active Directory (v1)`, and for **App ID URI**, enter the URI of the Azure AD Graph API:
```
https://graph.windows.net
diff --git a/articles/connections/enterprise/azure-active-directory/v1/index.md b/articles/connections/enterprise/azure-active-directory/v1/index.md
index 8efca26dcb..ec54bfa753 100644
--- a/articles/connections/enterprise/azure-active-directory/v1/index.md
+++ b/articles/connections/enterprise/azure-active-directory/v1/index.md
@@ -3,6 +3,18 @@ title: Connect your app to Azure Active Directory (Classic Portal)
description: How to obtain a ClientId and Client Secret for a Microsoft Azure Active Directory with the Classic Portal.
crews: crew-2
toc: true
+topics:
+ - connections
+ - enterprise
+ - azure
+ - active-directory
+ - microsoft
+contentType:
+ - index
+ - how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Connect your app to Azure Active Directory (Classic Portal)
@@ -19,7 +31,7 @@ There is no way to create an application that integrates with Microsoft Azure AD
## 1. Create a new Microsoft Azure Active Directory instance
-Login to Microsoft Azure and click on **Active Directory** on the Dashboard.
+Log in to Microsoft Azure, and select **Active Directory** from the Dashboard.

@@ -75,13 +87,13 @@ The next step is to modify permissions so your app can read the directory. Selec
If you want to enable extended attributes (like *Extended Profile* or *Security Groups*) you will also need to enable the following permissions: **Application Permissions:** *Read directory data*, **Delegated Permissions:** *Access your organization's directory*.
:::
-Click **SAVE** at the bottom of the screen and the key will be displayed. Make sure to copy the value of this key before leaving this screen.
+Click **Save** at the bottom of the screen and the key will be displayed. Make sure to copy the value of this key before leaving this screen.

## 4. Copy the Client ID and Secret to Auth0
-Login to your [Auth0 Dashboard](${manage_url}), and select the **Connections > Enterprise** menu option. Select **Windows Azure AD**.
+Go to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and select **Microsoft Azure AD**.
Copy the Client ID and the Key generated by Microsoft Azure in the [previous step](#configure-the-application) into the *Client ID* and *Client Secret* fields in Auth0.
@@ -93,7 +105,7 @@ Copy the Client ID and the Key generated by Microsoft Azure in the [previous ste
* When granting access, make sure to use an *Incognito/InPrivate* window and a Global Administrator user.
-* If you get *Access cannot be granted to this service because the service listing is not properly configured by the publisher*, try selecting the **Application is Multi Tenant** option in the Windows Azure AD application on the Azure dashboard.
+* If you get *Access cannot be granted to this service because the service listing is not properly configured by the publisher*, try selecting the **Application is Multi Tenant** option in the Windows Azure AD application in the Azure Dashboard.
## Signing Key Rollover in Azure Active Directory
diff --git a/articles/connections/enterprise/azure-active-directory/v2/index.md b/articles/connections/enterprise/azure-active-directory/v2/index.md
index 555b981d98..ce2f6ac9cd 100644
--- a/articles/connections/enterprise/azure-active-directory/v2/index.md
+++ b/articles/connections/enterprise/azure-active-directory/v2/index.md
@@ -1,7 +1,8 @@
---
-title: Connect your app to Microsoft Azure Active Directory
+title: Connect Your App to Microsoft Azure Active Directory
connection: Azure Active Directory
image: /media/connections/azure.png
+public: true
alias:
- azure-ad
- waad
@@ -10,158 +11,170 @@ alias:
- microsoft-azure-ad
- microsoft-azure-active-directory
seo_alias: azure-active-directory
-description: How to obtain a ClientId and Client Secret for Microsoft Azure Active Directory.
+description: Learn how to connect your app to Microsoft Azure Active Directory using an enterprise connection.
crews: crew-2
toc: true
+topics:
+ - connections
+ - enterprise
+ - azure
+ - active-directory
+ - microsoft
+contentType:
+ - how-to
+useCase:
+ - customize-connections
+ - add-idp
---
+# Connect Your App to Microsoft Azure Active Directory
-# Connect your app to Microsoft Azure Active Directory
+You can integrate with Microsoft Azure Active Directory (AD) if you want to let users:
-There are different scenarios in which you might want to integrate with Microsoft Azure AD:
-
-* You want to let users into your application from an Azure AD you or your organization controls (such as employees in your company).
-
-* You want to let users coming from other companies' Azure ADs into your application. You may want to set up those external directories as different connections.
-
-If you plan on allowing users to log in using a Microsoft Azure Active Directory account, either from your company or from external directories, you must register your application through the Microsoft Azure portal. If you don't have a Microsoft Azure account, you can [signup](https://azure.microsoft.com/en-us/free) for free.
-
-You can access the Azure management portal from your Microsoft service, or visit [https://manage.windowsazure.com](https://manage.windowsazure.com) and sign in to Azure using the global administrator account used to create the Office 365 organization.
+* From within your company use your application from an Azure AD controlled by you or your organization.
+* From other companies' Azure ADs use your application. (We recommend that you configure external directories as different connections.)
::: note
-There is no way to create an application that integrates with Microsoft Azure AD without having **your own** Microsoft Azure AD instance.
+Claims returned from the Azure AD enterprise connection are static; custom or optional claims will not appear in user profiles. If you need to include custom or optional claims in user profiles, use a SAML or OIDC connection instead.
:::
-If you have an Office 365 account, you can use the account's Azure AD instance instead of creating a new one. To find your Office 365 account's Azure AD instance:
-
-1. [Sign in](https://portal.office.com) to Office 365.
-2. Navigate to the [Office 365 Admin Center](https://portal.office.com/adminportal/home#/homepage).
-3. Open the **Admin centers** menu drawer located in the left menu.
-4. Click on **Azure AD**.
-
-This will bring you to the admin center of the Azure AD instance backing your Office 365 account.
+## Prerequisites
-## 1. Create a new application
+* [Register your app with Auth0](/getting-started/set-up-app)
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
+* Have an Azure account. If you don't, you can [sign up for free](https://azure.microsoft.com/en-us/free).
+* Have an Azure AD directory. If you don't, you can create one by following Microsoft's [Quickstart: Create a new tenant in Azure Active Directory - Create a new tenant for your organization](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-access-create-new-tenant#create-a-new-tenant-for-your-organization).
-Login to Microsoft Azure and choose **Azure Active Directory** from the sidebar.
+## Steps
-
+To connect your application to Azure AD, you must:
-Then under **MANAGE**, select **App registrations**.
+1. [Register your app with Azure AD](#register-your-app-with-azure-ad).
+2. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+3. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+4. [Test the connection](#test-the-connection).
-
+### Register your app with Azure AD
-Then click on the **+ ADD** button to add a new application.
+To register your app with Azure AD, see Microsoft's [Quickstart: Register an application with the Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app).
-Enter a name for the application, select **Web app/API** as the **Application Type**, and for **Sign-on URL** enter your application URL.
-
-
-
-## 2. Configure the permissions
-
-Once the application has been created, you will have to configure the permissions. Click on the name of the application to open the **Settings** section.
+::: warning
+If you have more than one Azure AD directory, make sure you are in the correct directory when you register the app you want to use with Auth0.
+:::
-
+During registration, configure the following settings:
-Click **Required permissions**.
+| Option | Setting |
+| -- | -- |
+| **Supported account types** | To allow users from external organizations (like other Azure AD directories) choose the appropriate multitenant option. Multitenant options include the following: **Accounts in any organizational directory (Any Azure AD directory - Multitenant)**. |
+| **Redirect URI** | Select a Redirect URI type of **Web**, and enter your callback URL: `https://${account.namespace}/login/callback`. |
-
+<%= include('../../../_find-auth0-domain-redirects.md') %>
-Then click on **Windows Azure Active Directory** to change the access levels.
+During this process, Microsoft generates an **Application (client) ID** for your application; you can find this on the app's **Overview** screen. **Make note of this value.**
-
+#### Create a client secret
-The next step is to modify permissions so your app can read the directory. Under **DELEGATED PERMISSIONS** check next to **Sign in and read user profile** and **Read directory data**.
+To create a client secret, see Microsoft's [Quickstart: Configure a client application to access web APIs - Add Credentials to your web application](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-credentials).
-
+Once generated, **make note of this value**.
::: note
-If you want to enable extended attributes (like *Extended Profile* or *Security Groups*) you will also need to enable the following permissions: **Application Permissions:** *Read directory data*, **Delegated Permissions:** *Access the directory as the signed-in user*.
+If you configure an expiring secret, make sure to **record the expiration date**; you will need to renew the key before that day to avoid a service interruption.
:::
-Click the **SAVE** button at the top to save these changes.
-
-## 3. Allowing access from external organizations (optional)
+#### Add permissions
-If you want to allow users from external organizations (such as other Azure directories) to log in, you will need to enable the **Multi-Tenant** flag for this application. In the **Settings** section, click **Properties**. Locate the **Multi-tenanted** toggle at the bottom and select **Yes**. Finally click the **SAVE** button at the top to save these changes.
+To add permissions, see Microsoft's [Quickstart: Configure a client application to access web APIs - Add permissions to access web APIs](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-permissions-to-access-web-apis).
-
+You will need to configure permissions for the **Microsoft Graph API**.
-## 4. Create the key
+While setting up your permissions, configure the following settings:
-Next you will need to create a key which will be used as the **Client Secret** in the Auth0 connection. Click on **Keys** from the **Settings** menu.
+| Field | Description |
+| -- | -- |
+| **Delegated permissions** | Required. |
+| **Users > User.Read** | So your app can sign in users and read the signed-in users' profiles. |
+| **Directory > Directory.Read.All** | So your app can read directory data on the signed-in user's behalf. |
-
+If you want to enable extended attributes (such as *Extended Profile* or *Security Groups*), then you also must configure the following settings:
-Enter a name for the key and choose the desired duration.
+| Field | Description |
+| -- | -- |
+| **Delegated permissions** | Under **Directory**, select **Directory.AccessAsUser.All** so your app can access the directory as the signed-in user. |
+| **Application Permissions** | Under **Directory**, select **Directory.Read.All** so your app can read directory data. |
-::: note
-If you choose an expiring key, make sure to record the expiration date in your calendar, as you will need to renew the key (get a new one) before that day in order to ensure users don't experience a service interruption.
-:::
-
-
+### Create an enterprise connection in Auth0
-Click on **Save** and the key will be displayed. **Make sure to copy the value of this key before leaving this screen**, otherwise you may need to create a new key. This value is used as the **Client Secret** in the next step.
+Create and configure an Azure AD Enterprise Connection in Auth0. Make sure you have the **Application (client) ID** and the **Client secret** generated when you set up your app in the Microsoft Azure portal.
-
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **Microsoft Azure AD**, and select its `+`.
-## 5. Configure Reply URLs
+
- Next you need to ensure that your Auth0 callback URL is listed in allowed reply URLs for the created application. Navigate to **Azure Active Directory** -> **Apps registrations** and select your app. Then click **Settings** -> **Reply URLs** and add:
+2. Enter details for your connection, and select **Create**:
- `https://${account.namespace}/login/callback`
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **Microsoft Azure AD Domain** | Your Azure AD domain name. You can find this on your Azure AD directory's overview page in the Microsoft Azure portal. |
+| **Client ID** | Unique identifier for your registered Azure AD application. Enter the saved value of the **Application (client) ID** for the app you just registered in Azure AD. |
+| **Client Secret** | String used to gain access to your registered Azure AD application. Enter the saved value of the **Client secret** for the app you just registered in Azure AD. |
+| **Use common endpoint** | (Optional) When enabled, your application will dynamically accept users from new directories. Typically enabled if you selected a multitenant option for **Supported account types** for the application you just registered in Azure AD. When enabled, Auth0 will redirect users to Azure's common login endpoint, and Azure will perform *Home Realm Discovery* based on the domain of the user's email address. |
+| **Identity API** | API used by Auth0 to interact with Azure AD endpoints. Learn about the differences in behavior in Microsoft's [Why update to Microsoft identity platform (v2.0)](https://docs.microsoft.com/en-us/azure/active-directory/develop/azure-ad-endpoint-comparison) doc. |
+| **Attributes** | Basic attributes for the signed-in user that your app can access. Indicates how much information you want stored in the Auth0 User Profile. |
+| **Extended Attributes** (optional) | Extended attributes for the signed-in user that your app can access. |
+| **Auth0 APIs** (optional) | When selected, indicates that we require the ability to make calls to the Azure AD API, which allows us to search for users in the Azure AD Graph even if they never logged in to Auth0. |
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
+| **Email Verification** | Choose how Auth0 sets the `email_verified` field in the user profile. To learn more, see [Email Verification for Azure AD and ADFS](/connections/azuread-adfs-email-verification). |
- 
+
- It has the following format `https://..auth0.com/login/callback` (`region` is omitted if the Auth0 tenant was created in the US).
+3. In the **Login Experience** view, you can configure how users log in with this connection.
- ::: note
- If you are using the [custom domains](/custom-domains) feature, your Reply URL will instead be in the following format: `https:///login/callback`.
- :::
+<%= include('../../_login-experience-tab.md') %>
- Without this step the App consent page will return a "Bad request" error. The fine print in the footer of this error page can be used to identify the exact tenant name and missing callback url.
+4. If you have appropriate Azure AD administrative permissions to *give consent* to the application so users can log in, then click **Continue**.
-## 6. Create Connections
+ You will be asked to [log in to your Azure AD account](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#requesting-consent-for-an-entire-tenant) and give consent. Otherwise, provide the given URL to your administrator so that they can give consent.
-Login to your [Auth0 Dashboard](${manage_url}), and select the **Connections > Enterprise** menu option.
+### Enable the enterprise connection for your Auth0 application
-
+To use your new Azure AD enterprise connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
-Select **Microsoft Azure AD**. You will be asked to provide the appropriate settings, including data about the app registration you just created in Auth0.
+### Test the connection
-
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
-For the **Client ID**, this value is stored as the **Application ID** in Azure AD.
-
-
+## Troubleshooting
-For the **Client Secret** use the value that was shown for the key when you created it in the previous step.
+Here are some troubleshooting tips:
-Set the name of the **Microsoft Azure AD Domain** and under **Domain Aliases** put any email domain that corresponds to the connection.
+**I registered my application with Azure AD, but when I go back to my Azure Active Directory App registrations, I can't see my application.**
-
+You may have accidentally registered your app in the wrong Azure AD directory (or not have created an Azure AD directory at all before registering your app). It's likely easiest to re-register your app in Azure AD. Make sure you are in the correct directory when you register the app. If you need to create an Azure AD directory, follow Microsoft's [Quickstart: Create a new tenant in Azure Active Directory - Create a new tenant for your organization](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-access-create-new-tenant#create-a-new-tenant-for-your-organization).
-**Multi-tenant applications**: if you are creating multi-tenant applications where you want to dynamically accept users from new directories, you will setup only one connection and enable the **Use Common Endpoint** toggle. By enabling this flag, Auth0 will redirect users to Azure's common login endpoint, and Azure itself will be doing *Home Realm Discovery* based on the domain of the email address.
+**I receive the following error message: "Access cannot be granted to this service because the service listing is not properly configured by the publisher".**
-Then choose the protocol. **Open ID Connect** is the default, and should be selected in the majority of cases. This is independent of the protocol that your application will use to connect to Auth0.
+To resolve this, try changing the **Supported account types** for your registered Azure AD app. Make sure you have chosen an appropriate multitenant option in the Azure AD app's Authentication settings. Multitenant options include the following: **Accounts in any organizational directory (Any Azure AD directory - Multitenant)**.
-Next complete the **App ID Uri** field if you intend to use [active authentication](/api/authentication#database-ad-ldap-active-), as explained in [Native Azure AD applications with Auth0](/connections/enterprise/azure-active-directory-native).
+**When users try to log in, we receive the following error message: "invalid_request; failed to obtain access token".**
-Click the **SAVE** button. Auth0 will provide you with a URL that you will need to give to the Azure AD administrator. This URL will allow the administrator to *give consent* to the application so that users can log in.
+The most likely reason for this error is an invalid or expired Azure AD **Client secret**. To resolve this, generate a new **Client secret** for your app in Azure AD, then update the **Client Secret** in the enterprise connection configured with Auth0.
-**Congratulations!** You are now ready to accept Microsoft Azure AD users.
+## Signing Key Rollover in Azure AD
-## Troubleshooting
+Signing keys are used by the identity provider to sign the authentication token it issues, and by the consumer application (Auth0 in this case) to validate the authenticity of the generated token.
-* Make sure you are in the desired directory to add you application. If you do not have an existing directory you will need to create one.
+For security purposes, Azure AD’s signing key [rolls on a periodic basis](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-signing-key-rollover). If this happens, **you do not need to take any action**. Auth0 will use the new key automatically.
-* When granting access, make sure to use an *Incognito/InPrivate* window and a Global Administrator user.
+<%= include('../../../_quickstart-links.md') %>
-* If you get *Access cannot be granted to this service because the service listing is not properly configured by the publisher*, try enabling **Multi Tenanted** in the Windows Azure AD application under **Settings** -> **Properties**.
+## Remove unverified label
-## Signing Key Rollover in Azure Active Directory
+If you're using a custom domain, the application consent prompt for Azure AD login may label your domain as "unverified". To remove the unverified label:
-Signing keys are used by the identity provider to sign the authentication token it issues, and by the consumer application (Auth0 in this case) to validate the authenticity of the generated token.
+1. Verify the domain for the Auth0 application: [Add your custom domain name using the Azure Active Directory portal](https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/add-custom-domain#add-your-custom-domain-name-to-azure-ad)
+2. Assign the verified domain to the Auth0 application: [How to: Configure an application's publisher domain](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-configure-publisher-domain#configure-publisher-domain-using-the-azure-portal)
-For security purposes, Azure AD’s signing key [rolls on a periodic basis](https://azure.microsoft.com/en-us/documentation/articles/active-directory-signing-key-rollover/). If this happens, **you do not need to take any action**. Auth0 will use the new key automatically.
-
-<%= include('../../../_quickstart-links.md') %>
diff --git a/articles/connections/enterprise/azuread-adfs-email-verification.md b/articles/connections/enterprise/azuread-adfs-email-verification.md
new file mode 100644
index 0000000000..19816db46a
--- /dev/null
+++ b/articles/connections/enterprise/azuread-adfs-email-verification.md
@@ -0,0 +1,63 @@
+---
+title: Email Verification for Azure AD and ADFS
+description: Learn how to control how the `email_verified` field is set for Azure AD and ADFS.
+toc: true
+topics:
+ - connections
+contentType: how-to
+---
+# Email Verification for Azure AD and ADFS connections
+
+Auth0 user's profile has an `email_verified` field, which can be set in different ways depending on the connection type. For database connections, users must go through an email validation flow to get the email verified. For federated connections, identity providers can return the `email_verified` field based on their own criteria.
+
+Azure AD and ADFS cannot guarantee that the emails they return have been verified:
+
+- In ADFS, the ADFS administrator can configure any email they want.
+
+- In Azure AD, depending on how the Azure AD tenant is configured, email addresses returned by Azure AD may or may not correspond to Office mailboxes. Auth0 can't know whether they do or not.
+
+However, if you know how an Azure AD or ADFS is configured and managed, you can decide to trust that the emails from those accounts are verified.
+
+To accommodate both needs, Azure AD and ADFS connections have an **Email Verification** property with two values:
+
+- Always set `email_verified` to `true`
+- Always set `email_verified` to `false`
+
+The Azure AD connection also has a **Use Common Endpoint** property. When it's enabled, the user can authenticate with any Azure AD tenant. Given it's not possible to trust that any Azure AD tenant will return verified emails, the **Email Verification** property will need to be set to **Always set `email_verified` to `false`**.
+
+When the property is set to **Always set `email_verified` to `false`**, users will get `email_verified` set to `false` the next time they log in, unless the [Sync user profile attributes at each login](/dashboard/guides/connections/configure-connection-sync) is disabled.
+
+## Azure AD/ADFS Email Verification Migration Setting
+
+In previous versions, Auth0 always set the `email_verified` field to true in Azure AD and ADFS connections. If you were using Azure AD and ADFS connections in the past, you will have a tenant setting that will override the Connection Setting for **Email Verification** and keep the previous behavior.
+
+You can find the new tenant setting in the [Auth0 Dashboard > Settings > Advanced](${manage_url}/#/tenant/advanced). Locate the **Migrations** section, then find **Default to 'Email Verification' setting for Azure AD/ADFS connections**.
+
+::: note
+This setting is only available if:
+
+* the tenant is older than the date the migration was introduced
+* the tenant has one or more active ADFS or Azure AD connection
+:::
+
+
+
+When this setting is disabled, `email_verified` will always be `true` for Azure AD/ADFS connections. When enabled, it will use the 'Email Verification' setting at the connection level.
+
+## Email Verification Flow for Azure AD/ADFS connections
+
+If your application requires that the emails from an Azure AD/ADFS connection's users are always verified, you can enable the **Enable email verification flow during login for Azure AD and ADFS connections** option in the tenant's **Advanced Settings** section.
+
+After the user authenticates for the first time with a non-verified email, Auth0 will ask the user to verify their email by entering a one-time-use code that will be sent to their email account:
+
+
+
+If the user completes this step, the `email_verified` field will be set to `true`, and users will not be prompted again for email verification, unless Azure AD or ADFS return a different email for the user.
+
+This new screen is rendered using the New Universal Login Experience, even if you have Universal Login configured to use the Classic Experience. To learn how to customize it, read the [Universal Login Customization documentation](/universal-login/customization-new).
+
+To learn how to customize the email that is sent to users, check the [Verification Email template documentation](/users/verify-emails/)
+
+:::warning
+When Azure AD does not return an `email` claim, Auth0 maps the [Azure UserPrincipalName](https://docs.microsoft.com/en-us/azure/active-directory/hybrid/plan-connect-userprincipalname) as the email. There is no guarantee that the UserPrincipalName value is a mailbox, so Auth0 will **NOT** display the email verification prompt and the user will have the field `email_verified` set to `false`.
+:::
diff --git a/articles/connections/enterprise/google-apps.md b/articles/connections/enterprise/google-apps.md
index ec60cb3fd4..19bfde226b 100644
--- a/articles/connections/enterprise/google-apps.md
+++ b/articles/connections/enterprise/google-apps.md
@@ -1,129 +1,120 @@
---
-title: Connecting Google Apps with Auth0
-connection: Google Apps
-image: /media/connections/googleapps.png
-seo_alias: google-apps
-description: Connecting Google Apps with Auth0.
+title: Connect Your App to Google Workspace
+connection: Google Workspace
+image: /media/connections/gsuite.png
+public: true
+seo_alias: g-suite
+description: Learn how to connect your app to Google Workspace using an enterprise connection.
crews: crew-2
toc: true
+topics:
+ - connections
+ - enterprise
+ - google
+ - workspace
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
+# Connect Your App to Google Workspace
-# Connect Your Google App with Auth0
-
-You can connect your Auth0 Application to Google Apps by providing the Google *Client ID* and *Client Secret* to Auth0.
-
-## Generate the Google Client ID and Client Secret
-
-1. While logged in to your Google account, go to the [API Manager](https://console.developers.google.com/projectselector/apis/credentials).
-
-2. Create your new app by navigating to **Credentials** using the left-hand menu:
-
- 
-
-3. While you are on the **Credentials** page, click on **Create a project**.
-
-4. In the dialog box that appears, provide a Project name, answer Google's email- and privacy-related questions, and click **Create**:
-
- 
+::: panel Using Google Social and Enterprise Connections
+If you have an existing [Google Social Connection](/connections/social/google) for your application and you create a new Google Workspace connection for the same domain, users affiliated with the social connection with now be logged in with the new enterprise connection. This will occur regardless of whether you enable the Google Workspace enterprise connection.
+:::
-5. Google will take a moment to create your project. When the process completes, Google will prompt you to create the credentials you need.
+## Prerequisites
- 
+ * [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
-6. Click on **Create credentials** to display a pop-up menu listing the types of credentials you can create. Select the **OAuth client ID** option.
+## Steps
-7. At this point, Google will display a warning banner that says, "To create an OAuth client ID, you must first set a product name on the consent screen." Click **Configure consent screen** to begin this process.
+To connect your application to Google Workspace, you must:
- 
+1. [Set up your app in Google](#set-up-your-app-in-google)
+2. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+3. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+4. [Test the connection](#test-the-connection).
-8. Provide a **Product Name** that will be shown to users when they log in through Google.
+::: panel Google Workspace Account
+Before proceeding, you will need a valid Google Workspace account and must have **your own** Google Workspace Organization for which you are an administrator.
+:::
- 
+## Set up your app in Google
-9. Click **Save**.
+To allow users to log in using Google Workspace, you must register your application in the Google developer console.
-::: note
-Google may show an "unverified app" screen before displaying the consent screen for your app. To remove the unverified app screen, complete the [OAuth Developer Verification](https://support.google.com/code/contact/oauth_app_verification) process.
+::: warning
+Before proceeding, you must have already set up **your own** Google Workspace Organization for which you are an administrator.
:::
-10. At this point, you will be prompted to provide additional information about your newly-created app.
-
- 
+### Register a new application
-11. Select **Web application**, and provide a name for your app.
+To learn how to register a new application with Google, follow Google's [Setting up OAuth 2.0](https://support.google.com/googleapi/answer/6158849) doc. During this process, Google will generate a **Client ID** and **Client Secret** for your application; make note of these.
-12. Under **Restrictions**, enter the following information:
+While setting up your app, be sure to use these settings:
- * **Authorized JavaScript origins:** `https://${account.namespace}`
- * **Authorized redirect URI:** `https://${account.namespace}/login/callback`
+* On the **OAuth consent screen**, under **Authorized domains**, add `auth0.com`.
+* When asked to select an application type, choose **Web application** and set the following parameters:
- ::: note
- If you are using the [custom domains](/custom-domains) feature, you will need to use your custom domain in the redirect URI in the following format: `https:///login/callback`.
- :::
+| Field | Description |
+| ----- | ----------- |
+| Name | The name of your application. |
+| Authorized JavaScript origins | `https://${account.namespace}` |
+| Authorized redirect URIs | `https://${account.namespace}/login/callback` |
-13. Click **Create**. Your `Client Id` and `Client Secret` will be displayed:
+<%= include('../_find-auth0-domain-redirects') %>
- 
-
- Save your `Client Id` and `Client Secret` to enter into the Connection settings in Auth0.
+::: warning
+If your application requests sensitive OAuth scopes, it may be [subject to review by Google](https://developers.google.com/apps-script/guides/client-verification).
+:::
### Enable the Admin SDK Service
-If you are planning to connect to Google Apps enterprise domains, you will need to enable the **Admin SDK** service.
-
-1. Navigate to the **Library** page of the API Manager.
-
-2. Select **Admin SDK** from the list of APIs:
-
- 
-
-3. On the **Admin SDK** page, click **Enable**.
+If you plan to connect to Google Workspace enterprise domains, you need to enable the **Admin SDK Service**. To learn how, follow Google's [Enable and disable APIs](https://support.google.com/googleapi/answer/6158841) doc.
- 
+## Create an enterprise connection in Auth0
-## Enable and Configure the Auth0 Enterprise Connection
+Next, you will need to create and configure a Google Workspace Enterprise Connection in Auth0. Make sure you have the **Client ID** and **Client Secret** generated when you set up your app in the Google developer console.
-1. Log in to your Auth0 account, and navigate to [Enterprise Connections](${manage_url}/#/connections/enterprise).
-2. Scroll down to the row for Google Apps, and click the **Add New** plus icon.
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **Google Workspace**, and click its `+`.
- 
+
- You will see the *Settings* page for the Google Apps Connection.
+2. Enter details for your connection, and select **Create**:
- 
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **Google Workspace Domain** | Google Workspace domain name for your organization. |
+| **Client ID** | Unique identifier for your registered Google application. Enter the saved value of the **Client ID** for the app you just registered in the Google developer console. |
+| **Client Secret** | String used to gain access to your registered Google application. Enter the saved value of the **Client Secret** for the app you just registered in the Google developer console. |
+| **Attributes** | Basic attributes for the signed-in user that your app can access. Indicates how much information you want stored in the Auth0 User Profile. Options include: **Basic Profile** (`email`, `email verified` flag) and **Extended Profile** (name, public profile URL, photo, gender, birthdate, country, language, and timezone). |
+| **Extended Attributes** | Extended attributes for the signed-in user that your app can access. Options include: **Groups** (distribution list(s) to which the user belongs), **Is Domain Administrator** (indicates whether the user is a domain administrator), **Is Account Suspended** (indicates whether the user's account is suspended), and **Agreed to Terms** (indicates whether the user has agreed to the terms of service). |
+| **Auth0 APIs** | When **Enable Users API** is selected, indicates that you require the ability to make calls to the Google Directory API. |
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
-3. On the Settings screen, provide the following information:
+
-| Parameter | Description |
-| - | - |
-| **Google Apps Domain** | the Google Apps domain you're using for authentication |
-| **Domain Aliases** (optional) | a comma-separated list of domains registered as aliases for the primary domain |
-| **Client ID** | the Client ID for your Google Apps Account |
-| **Client Secret** | the Client Secret for your Google Apps Account |
-| **Attributes** | the flag that indicates how much information you want stored in the Auth0 User Profile. Select one of the two options: **Basic Profile** (includes the `email` and the `email verified` flag) or **Extended Profile** (includes the name, public profile URL, photo, gender, birthdate, country, language, and timezone) |
-| **Extended Attributes: Groups** | the distribution list(s) to which the user belongs |
-| **Extended Attributes: Is Domain Administrator** | whether the user is a domain administrator or not |
-| **Extended Attributes: Is Account Suspended** | whether the user's account is suspended or not |
-| **Extended Attributes: Agreed to Terms** | whether the user's agreed to the terms of service or not |
-| Enable Users API | the flag that indicates whether you've chosen to enable the ability to make calls to the Google Directory API |
+3. If you have appropriate administrative permissions to configure your Google Workspace settings so you can use Google's Admin APIs, then click **Continue**. Otherwise, provide the given URL to your administrator so that they can adjust the required settings.
-Click **Save** when you're done.
+4. On the **Login Experience** tab you can configure how users log in with this connection.
-4. You will need to configure your settings so that your app can use Google's Admin APIs. If you're the administrator, you can click **Continue** on the Connection's *Settings* page to do so. If not, provide the URL you're given to your administrator so that they can adjust the required Settings.
+<%= include('./_login-experience-tab.md') %>
- 
+## Enable the enterprise connection for your Auth0 application
-## Enable the Connection for Your Auth0 Application
+To use your new AD connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
-To use your newly-created Connection, you'll need to enable it for your Auth0 Application(s).
+## Test the connection
-1. Go to the [Applications](${manage_url}/#/applications) page of the Management Dashboard.
-2. Select the Application for which you want to enable the Connection.
-3. Click the **Connections** icon for your Application.
-4. Scroll down to the *Enterprise* section of the Connections page, and find your Google Apps Connection. Click the slider to enable the Connection. If successful, the slide turns green.
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
-
+## Requesting Refresh Tokens from Google
-At this point, your users will be able to log in using their Google App credentials.
+Google always returns an Access Token, which is stored in the user profile. If you add `access_type=offline&approval_prompt=force` to the authorization request, Auth0 will forward these parameters to Google. Google will then return a Refresh Token, which will also be stored in the user profile.
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/enterprise/index.md b/articles/connections/enterprise/index.md
new file mode 100644
index 0000000000..b3bb2c147a
--- /dev/null
+++ b/articles/connections/enterprise/index.md
@@ -0,0 +1,18 @@
+---
+title: Enterprise Identity Providers
+description: Learn about enterprise identity providers supported by Auth0.
+topics:
+ - connections
+ - identity-providers
+contentType:
+ - reference
+useCase:
+ - customize-connections
+ - add-idp
+---
+# Enterprise Identity Providers
+
+Auth0 supports the following enterprise providers out of the box. You can also explore partner-supported enterprise connections through the [Auth0 Marketplace](https://marketplace.auth0.com/features/enterprise-connections).
+
+<% var enterpriseConnections = cache.find('articles/connections/enterprise', {sort: 'index'}); %>
+<%= include('../_connections', { connections: enterpriseConnections }) %>
\ No newline at end of file
diff --git a/articles/connections/enterprise/ip-address.md b/articles/connections/enterprise/ip-address.md
index 62976b6661..34374e2760 100644
--- a/articles/connections/enterprise/ip-address.md
+++ b/articles/connections/enterprise/ip-address.md
@@ -1,33 +1,68 @@
---
-title: Using IP Address Authentication with Auth0
+title: Connect Your App using IP Address Authentication [DEPRECATED]
connection: IP Address Authentication
-image: /media/connections/open-id.png
+image: /media/connections/ipaddress.png
+public: false
alias:
- ip-based-auth
- ip
- address-authentication
-seo_alias: ip-address
-description: How to use IP Address Authentication with Auth0.
-crews: crew-2
+description: Learn how to connect your app using IP Address Authentication with an enterprise connection. This feature has been deprecated.
+topics:
+ - connections
+ - enterprise
+ - ip-addresses
+useCase:
+ - customize-connections
+ - add-idp
---
-# Configure IP Address Authentication
+# Connect Your App using IP Address Authentication [DEPRECATED]
-For this type of connection, Auth0 checks if the request is coming from an IP Address within the specified range.
+::: warning
+ IP Address Authentication has been deprecated and will not be enabled for new customers. Existing customers who currently have IP Address Authentication enabled may continue to use this feature. If IP Address Authentication functionality is changed or removed from service at some point, customers who currently use it will be notified beforehand and given ample time to migrate.
+:::
-To configure this connection, navigate to [Dashboard > Connections](${manage_url}/#/connections/enterprise) and select the __IP Address Authentication__.
+When users connect to your app using IP Address Authentication, Auth0 checks whether the request is coming from within a specified range of IP addresses.
-Click __Create New Connection__ and fill in the required information.
+## Prerequisites
-Field | Description
-------|------------
-Connection Name | Descriptive name for the connection
-IP Range | Comma-separated list of IP Addresses, as specified in the [CIDR-notation](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) (for example, `192.168.100.14/24`)
-Default Username (Optional) | Default username assigned to anyone connecting from this range of IP addresses
+**Before beginning:**
-
+* [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
-Click __Save__.
+## Steps
-Next you will see a list of your registered [applications](${manage_url}/#/applications) with the option to enable the connection for any of them.
+To connect your application using IP Address Authentication, you must:
-That's it! You are now ready to test and start using your connection.
+1. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+2. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+3. [Test the connection](#test-the-connection).
+
+## Create an enterprise connection in Auth0
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **IP Address Authentication**, and click its `+`.
+
+
+
+2. Enter details for your connection, and click **Create**:
+
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **Display name** (optional) | Text used to customize the login button for Universal Login. When set, the Universal Login login button reads: "Continue with {Display name}". |
+| **Logo URL** (optional) | URL of image used to customize the login button for Universal Login. When set, the Universal Login login button displays the image as a 20px by 20px square. |
+| **IP Range** | Comma-separated list of IP Addresses and/or CIDR blocks, as specified in the [CIDR-notation](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). (For example, `192.168.100.14/24`). |
+| **Display username** | Generic username assigned to anyone connecting from this range of IP addresses. |
+
+
+
+## Enable the enterprise connection for your Auth0 application
+
+To use your new IP Address Authentication connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
+
+## Test the connection
+
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
diff --git a/articles/connections/enterprise/ldap.md b/articles/connections/enterprise/ldap.md
deleted file mode 100644
index e14a5d82cd..0000000000
--- a/articles/connections/enterprise/ldap.md
+++ /dev/null
@@ -1,54 +0,0 @@
----
-title: Using LDAP Authentication with Auth0
-connection: LDAP
-image: /media/connections/ldap.png
-seo_alias: ldap
-description: Using LDAP Authentication with Auth0.
----
-
-# Configure LDAP Authentication
-
-Auth0 lets you create [Lightweight Directory Access Protocol (LDAP)](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol) connections using the [Auth0 Dashboard](${manage_url}/#/connections/enterprise) and the [Active Directory/LDAP Connector](/connector).
-
-## Create a New Connection
-
-Start by creating a new connection. Navigate to [Dashboard > Connections > Enterprise](${manage_url}/#/connections/enterprise) and select **Active Directory / LDAP**.
-
-Click __Create New Connection__ and complete the form.
-
-Field | Description
-------|------------
-Connection Name | Descriptive name for the connection
-Email domains (optional) | List of valid domains for the connection
-Disable cache | Enable or disable caching
-Use application SSL certificate authentication | Enable or disable application SSL certificate authentication
-Use Windows Integrated Auth (Kerberos) | Enable or disable Kerberos authentication
-
-
-
-Click __SAVE__ to continue.
-
-## Set Up the Active Directory/LDAP Connector
-
-After creating the connection, you'll be prompted to set up the [Active Directory/LDAP Connector](/connector).
-
-
-
-Make note of the provided **Ticket URL** to use during the AD/LDAP Connector setup process, it should look something like this:
-
-```text
-https://${account.tenant}.auth0.com/p/ad/aBCdEfGh
-```
-
-Next, set up the AD/LDAP Connector by following the instructions for your platform:
-
-- [Install the AD/LDAP Connector on Windows](/connector/install)
-- [Install the AD/LDAP Connector on Non-Microsoft Platforms](/connector/install-other-platforms)
-
-## Test the Connection
-
-Once you've set up the AD/LDAP Connector, you can test your LDAP connection.
-
-Navigate to [Dashboard > Connections > Enterprise](${manage_url}/#/connections/enterprise), select **Active Directory / LDAP**, and click the **Try** button for your LDAP connection. You'll be directed to a login page where you can log in as a user and try the connection.
-
-That's it! You are now ready to start using your connection.
diff --git a/articles/connections/enterprise/o365-deprecated.md b/articles/connections/enterprise/o365-deprecated.md
index c420c2522d..a4db6cf5e7 100644
--- a/articles/connections/enterprise/o365-deprecated.md
+++ b/articles/connections/enterprise/o365-deprecated.md
@@ -2,11 +2,20 @@
title: Connect your app to Microsoft Office 365 (Deprecated)
connection: Office 365 (Deprecated)
image: /media/connections/office-365.png
+public: false
alias:
- office365
seo_alias: o365-deprecated
description: How to obtain a ClientId and Client Secret for an Office 365 connection.
toc: true
+topics:
+ - connections
+ - enterprise
+ - microsoft
+ - o365
+useCase:
+ - customize-connections
+ - add-idp
---
# Connect your app to Microsoft Office 365
@@ -17,8 +26,8 @@ See [here](/office365-deprecated) for more details.
To configure Microsoft Office 365 connections, you need to a register an application in the Seller Dashboard.
-## 1. Log into the Seller Dashboard
-Log into the [Seller Dashboard](https://sellerdashboard.microsoft.com), then select **client ids**.
+## 1. Log in to the Seller Dashboard
+Log in to the [Seller Dashboard](https://sellerdashboard.microsoft.com), then select **client ids**.

@@ -44,8 +53,6 @@ This is your only opportunity in Office 365 to copy the `ClientSecret`, it is no

-In your Auth0 dashboard, select **Connections > Enterprise**, then select **Office 365**.
-
-Copy the `ClientId` and `ClientSecret` from the Seller Dashboard into your Office 365 connection settings on this page.
+Navigate to [Auth0 Dashboard > Marketplace](${manage_url}/#/marketplace/office-365-sso), then select **SSO Integrations**, and locate **Office 365**, then[Configure the Office 365 connection](/integrations/sso/office-365).
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/enterprise/oidc.md b/articles/connections/enterprise/oidc.md
new file mode 100644
index 0000000000..eba713572c
--- /dev/null
+++ b/articles/connections/enterprise/oidc.md
@@ -0,0 +1,207 @@
+---
+connection: OpenID Connect
+image: /media/connections/oidc.png
+public: true
+seo_alias: oidc
+description: Learn how to connect to OpenID Connect (OIDC) Identity Providers using an enterprise connection.
+crews: crew-2
+toc: true
+topics:
+ - connections
+ - enterprise
+ - oidc
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+# Connect to OpenID Connect Identity Provider
+
+::: warning
+If you are using the Lock login widget with an OpenID Connect (OIDC) connection, you must use Lock version 11.16 or higher.
+:::
+
+## Prerequisites
+
+* [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
+
+## Steps
+
+To connect your application to an OIDC Identity Provider, you must:
+
+1. [Set up your app in the OpenID Connect Identity Provider](#set-up-your-app-in-the-openid-connect-identity-provider).
+2. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+3. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+4. [Test the connection](#test-the-connection).
+
+## Set up your app in the OpenID Connect Identity Provider
+
+To allow users to log in using an OIDC Identity Provider, you must register your application with the IdP. The process of doing this varies depending on the OIDC Identity Provider, so you will need to follow your IdP's documentation to complete this task.
+
+Generally, you will want to make sure that at some point you enter your callback URL: `https://${account.namespace}/login/callback`.
+
+<%= include('../_find-auth0-domain-redirects.md') %>
+
+During this process, your OIDC Identity Provider will generate a unique identifier for the registered API, usually called a **Client ID** or an **Application ID**. Make note of this value; you will need it later.
+
+## Create an enterprise connection in Auth0
+
+Next, you will need to create and configure a OIDC Enterprise Connection in Auth0. Make sure you have the **Application (client) ID** and the **Client secret** generated when you set up your app in the OIDC provider.
+
+### Create an enterprise connection using the Dashboard
+
+::: warning
+To be configurable through the Auth0 Dashboard, the OpenID Connect (OIDC) Identity Provider (IdP) needs to support [OIDC Discovery](https://openid.net/specs/openid-connect-discovery-1_0.html). Otherwise, you can configure the connection using the [Management API](#configure-the-connection-using-the-management-api).
+:::
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **Open ID Connect**, and click its `+`.
+
+
+
+2. Enter details for your connection, and select **Create**:
+
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **Issuer URL** | URL where Auth0 can find the **OpenID Provider Configuration Document**, which should be available in the `/.well-known/openid-configuration` endpoint. You can enter the base URL or the full URL. You will see a green checkmark if it can be found at that location, a red mark if it cannot be found, or an error message if the file is found but the required information is not present in the configuration file. |
+| **Client ID** | Unique identifier for your registered application. Enter the saved value of the **Client ID** for the app you registered with the OIDC Identity Provider. |
+| **Callback URL** | URL to which Auth0 redirects users after they authenticate. Ensure that this value is configured for the app you registered with the OIDC Identity Provider.
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
+
+<%= include('../_find-auth0-domain-redirects.md') %>
+
+
+
+3. In the **Settings** view, make additional configuration adjustments, if necessary.
+
+| Field | Description|
+| -- | -- |
+| **Issuer URL** | Click **Show Issuer Details** to view the Issuer URL **Advanced Settings** and make adjustments. |
+| **Type** | Set to **Front Channel** or **Back Channel**. Front Channel uses the OIDC protocol with `response_mode=form_post` and `response_type=id_token`. Back Channel uses `response_type=code`. |
+| **Scopes** | A comma-separated list of Auth0 scopes to request when connecting to the Identify Provider. This will affect the data stored in the user profile. You are required to include at least the `openid` scope. Note that the connection does not call `/userinfo` endpoint and expects the user claims to be present in the `id_token`. |
+
+4. In the **Login Experience** view, configure how users log in with this connection.
+
+<%= include('./_login-experience-tab.md') %>
+
+5. Select **Save Changes**.
+
+### Create an enterprise connection using the Management API
+
+These examples will show you the variety of ways you can create the [connection](/connections) using Auth0's Management API. You ca configure the connection by either providing a metadata URI or by setting the OIDC URLs explicitly.
+
+**Use Front Channel with discovery endpoint**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/connections",
+ "httpVersion": "HTTP/1.1",
+ "cookies": [],
+ "headers": [{
+ "name": "Authorization",
+ "value": "Bearer MGMT_API_ACCESS_TOKEN"
+ }],
+ "queryString": [],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"strategy\": \"oidc\", \"name\": \"CONNECTION_NAME\", \"options\": { \"type\": \"front_channel\", \"discovery_url\": \"https://IDP_DOMAIN/.well-known/openid-configuration\", \"client_id\" : \"IDP_CLIENT_ID\", \"scopes\": \"openid profile\" } }"
+ },
+ "headersSize": -1,
+ "bodySize": -1,
+ "comment": ""
+}
+```
+
+**Use Back Channel with discovery endpoint**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/connections",
+ "httpVersion": "HTTP/1.1",
+ "cookies": [],
+ "headers": [{
+ "name": "Authorization",
+ "value": "Bearer MGMT_API_ACCESS_TOKEN"
+ }],
+ "queryString": [],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"strategy\": \"oidc\", \"name\": \"CONNECTION_NAME\", \"options\": { \"type\": \"back_channel\", \"discovery_url\": \"https://IDP_DOMAIN/.well-known/openid-configuration\", \"client_id\" : \"IDP_CLIENT_ID\", \"client_secret\" : \"IDP_CLIENT_SECRET\", \"scopes\": \"openid profile\" } }"
+
+ },
+ "headersSize": -1,
+ "bodySize": -1,
+ "comment": ""
+}
+```
+
+**Use Back Channel specifying issuer settings**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/connections",
+ "httpVersion": "HTTP/1.1",
+ "cookies": [],
+ "headers": [{
+ "name": "Authorization",
+ "value": "Bearer MGMT_API_ACCESS_TOKEN"
+ }],
+ "queryString": [],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"strategy\": \"oidc\", \"name\": \"CONNECTION_NAME\", \"options\": { \"type\": \"back_channel\", \"issuer\": \"https://IDP_DOMAIN\", \"authorization_endpoint\": \"https://IDP_DOMAIN/authorize\", \"jwks_uri\": \"https://IDP_DOMAIN/.well-known/jwks.json\", \"client_id\" : \"IDP_CLIENT_ID\", \"scopes\": \"openid profile\" } }"
+ },
+ "headersSize": -1,
+ "bodySize": -1,
+ "comment": ""
+}
+```
+
+**Use Front Channel specifying issuer settings**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/connections",
+ "httpVersion": "HTTP/1.1",
+ "cookies": [],
+ "headers": [{
+ "name": "Authorization",
+ "value": "Bearer MGMT_API_ACCESS_TOKEN"
+ }],
+ "queryString": [],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"strategy\": \"oidc\", \"name\": \"CONNECTION_NAME\", \"options\": { \"type\": \"front_channel\", \"issuer\": \"https://IDP_DOMAIN\", \"authorization_endpoint\": \"https://IDP_DOMAIN/authorize\", \"token_endpoint\": \"https://IDP_DOMAIN/oauth/token\", \"jwks_uri\": \"https://IDP_DOMAIN/.well-known/jwks.json\", \"client_id\" : \"IDP_CLIENT_ID\", \"client_secret\" : \"IDP_CLIENT_SECRET\", \"scopes\": \"openid profile\" } }"
+ },
+ "headersSize": -1,
+ "bodySize": -1,
+ "comment": ""
+}
+```
+
+## Enable the enterprise connection for your Auth0 application
+
+To use your new enterprise connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
+
+## Test the connection
+
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
+
+## Manually configure Issuer metadata
+
+If you click `Show Issuer Details` on the Issuer URL endpoint, you can see the data and adjust it if you need to.
+
+## Federate with Auth0
+
+The OpenID Connect enterprise connection is extremely useful when federating to another Auth0 tenant. Just enter your Auth0 tenant URL (for example, `https://.us.auth0.com`) in the **Issuer** field, and enter the Client ID for any application in the tenant to which you want to federate in the **Client ID** field.
+
+::: note
+New tenants will have `us` as part of the URL. Tenants created before the regional domain addition will continue to work. For example, `https://{YOUR ACCOUNT}.auth0.com`.
+:::
diff --git a/articles/connections/enterprise/okta.md b/articles/connections/enterprise/okta.md
new file mode 100644
index 0000000000..24f4fc0078
--- /dev/null
+++ b/articles/connections/enterprise/okta.md
@@ -0,0 +1,116 @@
+---
+connection: Okta
+image: /media/connections/okta.png
+public: true
+seo_alias: okta
+description: Learn how to connect to Okta as an OpenID Connect (OIDC) Identity Provider using an enterprise connection.
+crews: crew-2
+toc: true
+topics:
+ - okta
+ - connections
+ - enterprise
+ - oidc
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+# Connect to Okta as an OpenID Connect Identity Provider
+
+::: warning
+If you are using the Lock login widget with an OpenID Connect (OIDC) connection, you must use Lock version 11.16 or higher.
+:::
+
+## Prerequisites
+
+* [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
+
+## Steps
+
+To connect your application to an OIDC Identity Provider, you must:
+
+1. [Register your app with Okta](#register-your-app-with-okta).
+2. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+3. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+4. [Test the connection](#test-the-connection).
+
+## Register your app with Okta
+
+To allow users to log in using Okta, you'll need to register your application. See [Register your app (Okta Documentation)](https://developer.okta.com/docs/guides/quickstart/website/register-app/) for full instructions.
+
+During registration you'll be prompted for **Sign-in redirect URIs**. Add your callback URL as a sign-in redirect URI:
+
+```text
+https://${account.namespace}/login/callback
+```
+
+<%= include('../_find-auth0-domain-redirects.md') %>
+
+Once you finish registering your application with Okta, save the **Client ID** and **Client secret** to use in the next step.
+
+## Create an enterprise connection in Auth0
+
+Next, you will need to create and configure a OIDC Enterprise Connection in Auth0. Make sure you have the **Application (client) ID** and the **Client secret** generated when you set up your app in the OIDC provider.
+
+### Create an enterprise connection using the Dashboard
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **Open ID Connect**, and click its `+`.
+
+
+
+2. Enter details for your connection, and select **Create**:
+
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **Issuer URL** | URL where Auth0 can find the **OpenID Provider Configuration Document**. For Okta this should be either of the following:
+
+* `https:///.well-known/openid-configuration`
+* `https:///oauth2//.well-known/`
+
+You can enter the base URL or the full URL. You will see a green checkmark if it can be found at that location, a red mark if it cannot be found, or an error message if the file is found but the required information is not present in the configuration file. |
+| **Client ID** | Unique identifier for your registered Okta application. Enter the saved value of the **Client ID** for the app you registered with the OIDC Identity Provider. |
+| **Callback URL** | URL to which Auth0 redirects users after they authenticate. Ensure that this value is configured for the app you registered with the OIDC Identity Provider.
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
+
+<%= include('../_find-auth0-domain-redirects.md') %>
+
+
+
+3. In the **Settings** view, make additional configuration adjustments, if necessary.
+
+| Field | Description|
+| -- | -- |
+| **Issuer URL** | Click **Show Issuer Details** to view the Issuer URL **Advanced Settings** and make adjustments. |
+| **Type** | Set to **Front Channel** or **Back Channel**. Front Channel uses the OIDC protocol with `response_mode=form_post` and `response_type=id_token`. Back Channel uses `response_type=code`. |
+| **Scopes** | A comma-separated list of Auth0 scopes to request when connecting to the Identify Provider. This will affect the data stored in the user profile. You are required to include at least the `openid` scope. Note that the connection does not call `/userinfo` endpoint and expects the user claims to be present in the `id_token`. |
+
+4. In the **Login Experience** view, configure how users log in with this connection.
+
+<%= include('./_login-experience-tab.md') %>
+
+5. Select **Save Changes**.
+
+::: note
+For instructions on creating an enterprise connection using the Management API, see [Connect to OpenID Connect Identity Provider](/connections/enterprise/oidc#create-an-enterprise-connection-using-the-management-api)
+:::
+
+## Enable the enterprise connection for your Auth0 application
+
+To use your new enterprise connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
+
+## Test the connection
+
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
+
+## Federate with Auth0
+
+The OpenID Connect enterprise connection is extremely useful when federating to another Auth0 tenant. Just enter your Auth0 tenant URL (for example, `https://.us.auth0.com`) in the **Issuer** field, and enter the Client ID for any application in the tenant to which you want to federate in the **Client ID** field.
+
+::: note
+New tenants will have `us` as part of the URL. Tenants created before the regional domain addition will continue to work. For example, `https://{YOUR ACCOUNT}.auth0.com`.
+:::
diff --git a/articles/connections/enterprise/ping-federate.md b/articles/connections/enterprise/ping-federate.md
index f7cedad748..6d5703f670 100644
--- a/articles/connections/enterprise/ping-federate.md
+++ b/articles/connections/enterprise/ping-federate.md
@@ -6,37 +6,85 @@ public: true
alias:
- pingfederate
seo_alias: ping-federate
-description: Create a connection between a PingFederate Server and Auth0.
+description: Learn how to create an enterprise connection between a PingFederate Server and Auth0.
+topics:
+ - connections
+ - enterprise
+ - pingfederate
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Connect Your PingFederate Server to Auth0
-Auth0 lets you create [PingFederate Server](https://documentation.pingidentity.com/pingfederate/pf84/#gettingStartedGuide/concept/gettingStarted.html) connections using the [Auth0 Dashboard](${manage_url}/#/connections/enterprise).
+Auth0 lets you create [PingFederate Server](https://documentation.pingidentity.com/pingfederate/pf84/#gettingStartedGuide/concept/gettingStarted.html) connections.
-## Create a New Connection
+## Prerequisites
-Navigate to [Dashboard > Connections > Enterprise](${manage_url}/#/connections/enterprise) and select **PingFederate**.
+**Before beginning:**
-Click __Create New Connection__ and complete the form.
+* [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
-Field | Description
-------|------------
-Connection Name | A descriptive name for the connection.
-Email Domains (Optional) | A comma-separated list of valid domains. Only needed if you want to use the [Lock login widget](/libraries/lock).
-PingFederate Server URL | The URL for your PingFederate Server.
-X509 Signing Certificate | The PingFederate Server public key encoded in PEM or CER format. See the [PingFederate documentation](https://documentation.pingidentity.com/pingfederate/pf84/index.shtml#concept_digitalSignatureSettings.html) for instructions on managing your server's certificates.
-Sign Request | Enable or disable signing of the SAML authentication request. If enabled, you'll need to provide the PingFederate server with your [tenant's certificate](https://${account.namespace}/pem).
-Sign Request Algorithm | The algorithm Auth0 will use to sign the SAML assertions. Ensure this matches your PingFederate Server's configuration.
-Sign Request Algorithm Digest | The algorithm Auth0 will use for the sign request digest. Ensure this matches your PingFederate Server's configuration.
+## Steps
-
+As long as your server is configured in the standard way, to connect your PingFederate server to Auth0 you must:
-Click __SAVE__ to continue.
+1. [Get the signing certificate from the IdP](#get-the-signing-certificate-from-the-idp) and [convert it to Base64](#convert-signing-certificate-to-base64).
+2. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+3. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+4. [Test the connection](#test-the-connection).
-## Test the Connection
+::: warning
+If additional setup is required for your server (such as attribute mapping), then you must [create a new SAML enterprise connection](/connections/enterprise/saml) instead.
+:::
-Once you've configured your PingFederate connection settings, you can test the connection.
+## Get the signing certificate from the IdP
-Navigate to [Dashboard > Connections > Enterprise](${manage_url}/#/connections/enterprise), select **PingFederate**, and click the **Try** button for your PingFederate connection. You'll be directed to a login page where you can log in as a user and try the connection.
+With PingFederate Server, Auth0 acts as the service provider, so you will need to retrieve an X.509 signing certificate from the IdP (in PEM or CER format); later, you will upload this to Auth0. The methods for retrieving this certificate vary, so please see the [PingFederate documentation](https://documentation.pingidentity.com/pingfederate/pf84/index.shtml#concept_digitalSignatureSettings.html) for instructions on managing your server's certificates.
-That's it! You are now ready to start using your connection.
+### Convert signing certificate to Base64
+
+Before you upload the X.509 signing certificate to Auth0, you must convert the file to Base64. To do this, either use a [simple online tool](https://www.base64decode.org/) or run the following command in Bash: `cat signing-cert.crt | base64`.
+
+## Create an enterprise connection in Auth0
+
+Next, if your server is configured in the standard way, you will need to create and configure a PingFederate Enterprise Connection in Auth0 and upload your X.509 signing certificate. This task can be performed using Auth0's Dashboard.
+
+::: warning
+If additional setup is required for your server (such as attribute mapping), then you must [create a new SAML enterprise connection](/connections/enterprise/saml) instead.
+:::
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **Ping Federate**, and select its `+`.
+
+
+
+2. Enter details for your connection, and select **Create**:
+
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant. Once set, this name can't be changed. |
+| **PingFederate Server URL** | URL for your PingFederate Server. |
+| **X.509 Signing Certificate** | PingFederate Server public key (encoded in PEM or CER) you retrieved from the IdP earlier in this process. |
+| **Sign Request** | When enabled, the SAML authentication request will be signed. (Be sure to download and provide the PingFederate server with your [tenant's certificate](https://${account.namespace}/pem).) |
+| **Sign Request Algorithm** | Algorithm Auth0 will use to sign the SAML assertions. Ensure this matches your PingFederate Server's configuration. |
+| **Sign Request Digest Algorithm** | Algorithm Auth0 will use for the sign request digest. Ensure this matches your PingFederate Server's configuration. |
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
+
+
+
+3. In the **Login Experience** view, configure how users log in with this connection.
+
+<%= include('./_login-experience-tab.md') %>
+
+## Enable the enterprise connection for your Auth0 application
+
+To use your new PingFederate enterprise connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
+
+## Test the connection
+
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
diff --git a/articles/connections/enterprise/saml.md b/articles/connections/enterprise/saml.md
new file mode 100644
index 0000000000..f639dc52cc
--- /dev/null
+++ b/articles/connections/enterprise/saml.md
@@ -0,0 +1,281 @@
+---
+title: Connect Your App to SAML Identity Providers
+connection: SAML
+image: /media/connections/saml.png
+public: true
+alias:
+ - saml
+seo_alias: saml
+description: Learn how to connect to SAML Identity Providers using an enterprise connection.
+topics:
+ - connections
+ - enterprise
+ - saml
+ - saml-p
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+# Connect Your App to SAML Identity Providers
+
+Auth0 lets you create SAML Identity Provider (IdP) connections.
+
+## Prerequisites
+
+**Before beginning:**
+
+* [Register your Application with Auth0](/getting-started/set-up-app).
+ * Select an appropriate **Application Type**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include the appropriate flows.
+* Decide on the name of this enterprise connection
+ * The Post-back URL (also called Assertion Consumer Service URL) becomes: `https://YOUR_DOMAIN/login/callback?connection=YOUR_CONNECTION_NAME`
+ * The Entity ID becomes: `urn:auth0:YOUR_TENANT:YOUR_CONNECTION_NAME`
+
+## Steps
+
+To connect your application to a SAML Identity Provider, you must:
+
+1. Enter the Post-back URL and Entity ID at the IdP (read the separate article here: https://auth0.com/docs/protocols/saml-configuration-options/saml-identity-provider-configuration-settings)
+2. [Get the signing certificate from the IdP](#get-the-signing-certificate-from-the-idp) and [convert it to Base64](#convert-signing-certificate-to-base64).
+3. [Create an enterprise connection in Auth0](#create-an-enterprise-connection-in-auth0).
+4. [Enable the enterprise connection for your Auth0 Application](#enable-the-enterprise-connection-for-your-auth0-application).
+5. [Set up mappings](#set-up-mappings) (unnecessary for most cases).
+6. [Test the connection](#test-the-connection).
+
+## Get the signing certificate from the IdP
+
+With SAML Login, Auth0 acts as the service provider, so you will need to retrieve an X.509 signing certificate from the SAML IdP (in PEM or CER format); later, you will upload this to Auth0. The methods for retrieving this certificate vary, so please see your IdP's documentation if you need additional assistance.
+
+### Convert signing certificate to Base64
+
+Before you upload the X.509 signing certificate to Auth0, you must convert the file to Base64. To do this, either use a [simple online tool](https://www.base64decode.org/) or run the following command in Bash: `cat signing-cert.crt | base64`.
+
+## Create an enterprise connection in Auth0
+
+Next, you will need to create and configure a SAML Enterprise Connection in Auth0 and upload your X.509 signing certificate. This task can be performed using either Auth0's Dashboard or Management API.
+
+### Create an enterprise connection using the Dashboard
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), locate **SAML**, and select its `+`.
+
+
+
+2. Enter details for your connection, and select **Create**:
+
+| Field | Description |
+| ----- | ----------- |
+| **Connection name** | Logical identifier for your connection; it must be unique for your tenant and the same name used when setting the Post-back URL and Entity ID at the IdP. Once set, this name can't be changed. |
+| **Sign In URL** | SAML single login URL. |
+| **X.509 Signing Certificate** | Signing certificate (encoded in PEM or CER) you retrieved from the IdP earlier in this process. |
+| **Sign Out URL** (optional) | SAML single logout URL. |
+| **User ID Attribute** (optional) | Attribute in the SAML token that will be mapped to the `user_id` property in Auth0. |
+| **Debug Mode** | When enabled, more verbose logging will be performed during the authentication process. |
+| **Sign Request** | When enabled, the SAML authentication request will be signed. (Be sure to download and provide the accompanying certificate so the SAML IdP can validate the assertions' signature.) |
+| **Sign Request Algorithm** | Algorithm Auth0 will use to sign the SAML assertions. |
+| **Sign Request Digest Algorithm** | Algorithm Auth0 will use for the sign request digest. |
+| **Protocol Binding** | HTTP binding supported by the IdP. |
+| **Request Template** (optional) | Template that formats the SAML request. |
+| **Sync user profile attributes at each login** | When enabled, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. |
+
+
+
+3. In the **Login Experience** view, configure how users log in with this connection.
+
+<%= include('./_login-experience-tab.md') %>
+
+4. If you have appropriate administrative permissions to complete the integration, click **Continue** to learn about the custom parameters needed to configure your IdP. Otherwise, provide the given URL to your administrator so that they can adjust the required settings.
+
+### Create an enterprise connection using the Management API
+
+You can also use the [Management API](/api/management/v2#!) to create your SAML Connection. When doing so, you may choose to specify each SAML configuration field manually or else specify a SAML metadata document that contains the configuration values.
+
+#### Create a connection using specified values
+
+1. Make a `POST` call to the [Create a Connection endpoint](/api/management/v2#!/Connections/patch_connections_by_id). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `CONNECTION_NAME`, `SIGN_IN_ENDPOINT_URL`, `SIGN_OUT_ENDPOINT_URL`, and `BASE64_SIGNING_CERT` placeholder values with your Management API Access Token, connection name, sign in URL, sign out URL, and Base64-encoded signing certificate (in PEM or CER format), respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/connections",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"strategy\": \"samlp\", \"name\": \"CONNECTION_NAME\", \"options\": { \"signInEndpoint\": \"SIGN_IN_ENDPOINT_URL\", \"signOutEndpoint\": \"SIGN_OUT_ENDPOINT_URL\", \"signatureAlgorithm\": \"rsa-sha256\", \"digestAlgorithm\": \"sha256\", \"fieldsMap\": {}, \"signingCert\": \"BASE64_SIGNING_CERT\" } }"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:connections`. |
+| `CONNECTION_NAME` | Τhe name of the connection to be created. |
+| `SIGN_IN_ENDPONT_URL` | SAML single login URL for the connection to be created. |
+| `SIGN_OUT_ENDPOINT_URL` | SAML single logout URL for the connection to be created. |
+| `BASE64_SIGNING_CERT` | X.509 signing certificate (encoded in PEM or CER) you retrieved from the IdP.|
+
+Or, in JSON:
+
+```json
+{
+ "strategy": "samlp",
+ "name": "CONNECTION_NAME",
+ "options": {
+ "signInEndpoint": "SIGN_IN_ENDPOINT_URL",
+ "signOutEndpoint": "SIGN_OUT_ENDPOINT_URL",
+ "signatureAlgorithm": "rsa-sha256",
+ "digestAlgorithm": "sha256",
+ "fieldsMap": {
+ ...
+ },
+ "signingCert": "BASE64_SIGNING_CERT"
+ }
+}
+```
+
+#### Create a connection using SAML metadata
+
+Rather than specifying each SAML configuration field, you can specify a SAML metadata document that contains the configuration values. When specifying a SAML metadata document, you may provide either the XML content of the document (`metadataXml`) or the URL of the document (`metadataUrl`). When providing the URL, content is downloaded only once; the connection will not automatically reconfigure if the content of the URL changes in the future.
+
+##### Provide metadata document content
+
+Use the `metadataXml` option to provide content of the document:
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/connections",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"strategy\": \"samlp\", \"name\": \"CONNECTION_NAME\", \"options\": { \"metadataXml\": \"...\" } }"
+ },
+ "headersSize": -1,
+ "bodySize": -1,
+ "comment": ""
+}
+```
+
+##### Provide a metadata document URL
+
+Use the `metadataUrl` option to provide the URL of the document:
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/connections",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"strategy\": \"samlp\", \"name\": \"CONNECTION_NAME\", \"options\": { \"metadataUrl\": \"https://saml-idp/samlp/metadata/uarlU13n63e0feZNJxOCNZ1To3a9H7jX\" } }"
+ }
+}
+```
+
+When providing the URL, content is downloaded only once; the connection will not automatically reconfigure if the content of the URL changes in the future.
+
+##### Refresh existing connection information with metadata URL
+
+::: note
+This process will only work if the connection was created with `metadataUrl` manually.
+:::
+
+If you have a B2B implementation and federate to Auth0 with your own SAML identity provider, you may need to refresh connection information stored in Auth0, such as signing certificate changes, endpoint URL changes, or new assertion fields. Auth0 does this automatically for ADFS connections, but not for SAML connections.
+
+You can create a batch process (cron job) to do a periodic refresh. The process can run every few weeks and perform a PATCH call to `/api/v2/connections/CONNECTION_ID` endpoint, passing a body containing `{options: {metadataUrl: '$URL'}}` where `$URL` is the same metadata URL with which you created the connection. You use the metadata URL to create a new temporary connection, then compare the properties of the old and new connections. If anything is different, update the new connection and then delete the temporary connection.
+
+1. Create SAML connection with `options.metadataUrl`. The connection object will be populated with information from the metadata.
+
+2. Update metadata content in the URL.
+
+3. Send a PATCH to the `/api/v2/connections/CONNECTION_ID` endpoint with `{options: {metadataUrl: '$URL'}}`. Now the connection object is updated with the new metadata content.
+
+## Specify a custom Entity ID
+
+To specify a custom Entity ID, use the Management API to override the default `urn:auth0:YOUR_TENANT:YOUR_CONNECTION_NAME.` Set the `connection.options.entityID` property when the connection is first created or by updating an existing connection.
+
+The JSON example below can be used to create a new SAML connection using the SAML IdP’s metadata URL while also specifying a custom Entity ID. The Entity ID is still unique since it is created using the name of the connection.
+
+```json
+{
+ "strategy": "samlp",
+ "name": "CONNECTION_NAME",
+ "options": {
+ "metadataUrl": "https://saml-idp/samlp/metadata/uarlU13n63e0feZNJxOCNZ1To3a9H7jX",
+ "entityId": "urn:your-custom-sp-name:YOUR_CONNECTION_NAME"
+ }
+}
+```
+
+## Enable the enterprise connection for your Auth0 application
+
+To use your new SAML enterprise connection, you must first [enable the connection](/dashboard/guides/connections/enable-connections-enterprise) for your Auth0 Applications.
+
+## Set up mappings
+
+::: warning
+If you're configuring a SAML enterprise connection for a non-standard PingFederate Server, you **must** update the attribute mappings.
+:::
+
+Select the **Mappings** view, enter mappings between the `{}`, and select **Save**.
+
+
+
+**Mappings for non-standard PingFederate Servers:**
+
+```json
+{
+ "user_id": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
+ "email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
+}
+```
+
+**Mappings for SSO Circle**
+
+```json
+{
+ "email": "EmailAddress",
+ "given_name": "FirstName",
+ "family_name": "LastName"
+}
+```
+
+**Map either of two claims to one user attribute**
+
+```json
+{
+ "given_name": [
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
+ ]
+}
+````
+
+**How to map name identifier to a user attribute**
+
+```json
+{
+ "user_id": [
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn",
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
+ ]
+}
+```
+
+## Test the connection
+
+Now you're ready to [test your connection](/dashboard/guides/connections/test-connections-enterprise).
diff --git a/articles/connections/enterprise/samlp.md b/articles/connections/enterprise/samlp.md
deleted file mode 100644
index 9b1afc6415..0000000000
--- a/articles/connections/enterprise/samlp.md
+++ /dev/null
@@ -1,109 +0,0 @@
----
-title: Connecting SAML Providers with Auth0
-connection: SAMLP
-image: /media/connections/saml.png
-alias:
- - saml
-seo_alias: samlp
-description: Connecting SAML Providers with Auth0
----
-
-# Create a SAMLP Identity Provider Connection
-
-Auth0 allows you to create SAMLP Identity Provider connections using either the Management [Dashboard](${manage_url}/#/connections/enterprise) or [API](/api/management/v2#!/Connections/post_connections).
-
-## Obtain IdP Signing Certificates
-
-When you're setting up a SAMLP Connection, Auth0 acts as the service provider. As such, you will need to retrieve and provide to Auth0 an X509 signing certificate from the SAML IDP in PEM or CER format. The methods for retrieving this certificate vary, so please see your identity provider for additonal assistance if necessary.
-
-### Convert the Signing Certificate to Base64
-
-Prior to uploading the X509 signing certificate to Auth0, you'll need to convert the file to Base64. You can use a simple online tool like [this one](https://www.base64decode.org/), or you can run the following in Bash: `cat signing-cert.crt | base64`
-
-## Create a Connection Using the Management Dashboard
-
-Log into the [Management Dashboard](${manage_url}), and navigate to [Connections > Enterprise](${manage_url}/#/connections/enterprise).
-
-
-
-Scroll down to the row for *SAMLP Identity Provider* and click **Add New** (which is represented by the plus symbol). You'll see the *Settings* page for your new Connection.
-
-
-
-Provide the following information for your new Connection:
-
-* **Connection Name**: The logical identifier for your Connection
-* **Email Domains** (optional): A comma-separated list of domains for [use with Lock](/libraries/lock)
-* **Sign In URL**: The SAML single login URL
-* **X509 Signing Certificate**: The signing certificate (encoded in PEM or CER) provided by the identity provider
-* **Sign Out URL** (optional): The SAML single logout URL
-* **User ID Attribute** (optional): The attribute in the SAML token that maps to the Auth0 `user_id` property
-* **Debug Mode**: Toggle this to enable/disable verbose logging during the authentication process
-* **Sign Request**: Toggle this to enable/disable signing of the authentication request (be sure to download and provide the accompanying certificate so the identity provider can validate the assertion's signature)
-* **Sign Request Algorithm**: The algorithm you want Auth0 to use to sign the SAML assertions
-* **Sign Request Digest Algorithm**: The algorithm you want to use for the sign request digest
-* **Protocol Binding**: The HTTP binding supported by the identity provider
-* **Request Template** (optional): The template that formats the SAML request
-
-Click **Save** to persist your changes.
-
-You will then see a pop-up window with the next steps you need to take.
-
-
-
-If you do not have the appropriate administrative permissions to complete the integration, you will see a URL to provide to someone who does. If you do, click **Continue** to see the instructions on how to configure the identity provider you want to use with this integration. You will also be provided the custom parameters needed to integrate your Auth0 tenant with the identity provider.
-
-
-
-## Create a Connection Using the Management API
-
-Instead of using the [Management Dashboard](${manage_url}), you can use the [Management API](/api/management/v2#!) to create your SAMLP Connection. You'll need to make the appropriate `POST` call to the [`post_connections` endpoint](/api/management/v2#!/Connections/post_connections).
-
-```json
-{
- "strategy": "samlp",
- "name": "CONNECTION_NAME",
- "options": {
- "signInEndpoint": "SIGN_IN_ENDPOINT_URL",
- "signOutEndpoint": "SIGN_OUT_ENDPOINT_URL",
- "signatureAlgorithm": "rsa-sha256",
- "digestAlgorithm": "sha256",
- "fieldsMap": {
- ...
- },
- "signingCert": "BASE64_SIGNING_CERT"
- }
-}
-```
-
-Here's how you might include the call within your application's code:
-
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/api/v2/connections",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [{
- "name": "Authorization",
- "value": "Bearer MGMT_API_ACCESS_TOKEN"
- }],
- "queryString": [],
- "postData": {
- "mimeType": "application/json",
- "text": "{ \"strategy\": \"samlp\", \"name\": \"CONNECTION_NAME\", \"options\": { \"signInEndpoint\": \"SIGN_IN_ENDPOINT_URL\", \"signOutEndpoint\": \"SIGN_OUT_ENDPOINT_URL\", \"signatureAlgorithm\": \"rsa-sha256\", \"digestAlgorithm\": \"sha256\", \"fieldsMap\": {}, \"signingCert\": \"BASE64_SIGNING_CERT\" } }"
- },
- "headersSize": -1,
- "bodySize": -1,
- "comment": ""
-}
-```
-
-## Enable the Connection for Your Auth0 Application
-
-To use your newly-created Connection, you'll need to enable it for your Auth0 Application(s).
-
-1. Go to the [Applications](${manage_url}/#/applications) page of the Management Dashboard.
-2. Select the Application for which you want to enable the Connection.
-3. Click the **Connections** icon for your Application.
-4. Scroll down to the *Enterprise* section of the Connections page, and your Connection. Click the slider to enable the Connection. If successful, the slide turns green.
diff --git a/articles/connections/enterprise/sharepoint-apps.md b/articles/connections/enterprise/sharepoint-apps.md
index 89fc927763..439966e375 100644
--- a/articles/connections/enterprise/sharepoint-apps.md
+++ b/articles/connections/enterprise/sharepoint-apps.md
@@ -1,12 +1,21 @@
---
-title: Connect your app to SharePoint Apps
+title: Connect Your App to SharePoint Apps
connection: SharePoint Apps
image: /media/connections/sharepoint.png
+public: false
alias:
- sharepoint-online
- sharepoint
seo_alias: sharepoint-apps
-description: About connecting SharePoint Apps with Auth0.
+description: Learn how to connect your app to SharePoint Apps with Auth0.
+topics:
+ - connections
+ - enterprise
+ - sharepoint
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Connect your app to SharePoint Apps
diff --git a/articles/connections/enterprise/ws-fed.md b/articles/connections/enterprise/ws-fed.md
index 6ff61228ac..efbad677e5 100644
--- a/articles/connections/enterprise/ws-fed.md
+++ b/articles/connections/enterprise/ws-fed.md
@@ -2,31 +2,37 @@
title: Connecting WS-Federation Providers with Auth0
connection: WS-Federation
image: /media/connections/wsfed.png
-public: true
+public: false
seo_alias: ws-fed
description: Connecting WS-Federation Providers with Auth0
+topics:
+ - connections
+ - enterprise
+ - ws-fed
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
# Connecting WS-Federation Providers with Auth0
To create a connection for a WS-Federation Identity Provider (such as Azure ACS/AD or IdentityServer) use the [ADFS connection](/connections/enterprise/adfs) type when creating your new connection.
-To configure this connection, navigate to [Dashboard > Connections > Enterprise](${manage_url}/#/connections/enterprise) and select the __ADFS__.
+To configure this connection, navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and select __ADFS__.

Click __Create New Connection__ and enter the following information:
* __Connection Name__ - A descriptive name for the connection
-* __Email Domains__ - (Optional) A comma-separated list of valid domains. Only needed if you want to use the [Lock login widget](/libraries/lock).
+* __Email Domains__ - (Optional) A comma-separated list of valid domains. Only needed if you want to use the Lock login widget.
-Next, you must either provide the URL for your WS-Federation server in the __ADFS URL__ field or upload a Federation Metadata file.
+Next, either provide the URL for your WS-Federation server in the __ADFS URL__ field or upload a Federation Metadata file.
-
+If you configure the connection with a WS-Federation server URL, Auth0 will retrieve the Federation Metadata endpoint and import the required parameters, certificates, and URLs. You must make sure that the URL is publicly accessible and the SSL certificate on your ADFS installation is valid.
-::: note
-If you configure the connection with a WS-Federation server URL, Auth0 will retrieve the Federation Metadata endpoint and import the required parameters, certificates, and URLs.
-:::
+
Click __Save__.
diff --git a/articles/connections/generic-oauth2-connection-examples.md b/articles/connections/generic-oauth2-connection-examples.md
index 17f70419cc..33aa05f5d9 100644
--- a/articles/connections/generic-oauth2-connection-examples.md
+++ b/articles/connections/generic-oauth2-connection-examples.md
@@ -1,17 +1,20 @@
---
description: This document covers generic OAuth 1.0/2.0 examples.
toc: true
+topics:
+ - connections
+ - oauth2
+contentType: concept
+useCase:
+ - customize-connections
+ - add-idp
---
# Generic OAuth 1.0 and 2.0 Examples
-::: note
- The recommended method for creating custom Social Connections is to use Auth0's Custom Social Connections Extension. The information in this article should be used for reference purposes only.
-:::
-
-Adding [OAuth 1.0](/oauth1) and [OAuth 2.0](/oauth2) providers as Connections allow you to support providers that are not currently built-in to the [Auth0 Management Dashboard](${manage_url}), like [DigitalOcean](#digitalocean), [Tumblr](#tumblr), and more.
+Adding [OAuth 1.0](/oauth1) and [OAuth 2.0](/oauth2) providers as Connections allow you to support providers that are not currently built-in to the [Auth0 Dashboard](${manage_url}), like [DigitalOcean](#digitalocean), [Tumblr](#tumblr), and more.
-This document covers examples of OAuth 1.0/2.0 Connections that you can create by making the appropriate `POST` call to the [Auth0 APIv2's Connections endpoint](/api/v2#!/Connections/post_connections). Please note that doing so requires an [APIv2 token](/api/v2/tokens) with `create:connections` scope.
+This document covers examples of OAuth 1.0/2.0 Connections that you can create by making the appropriate `POST` call to the [Auth0 APIv2's Connections endpoint](/api/v2#!/Connections/post_connections). Please note that doing so requires an [APIv2 token](/api/v2/tokens) with `create:connections` scope.
## DigitalOcean
@@ -101,7 +104,7 @@ This document covers examples of OAuth 1.0/2.0 Connections that you can create b
Generate an RSA keypair with the following command (or any equivalent method):
```bash
-$ openssl genrsa -out EXAMPLE.key 2048 && openssl rsa -pubout -in EXAMPLE.key -out EXAMPLE.pub
+openssl genrsa -out EXAMPLE.key 2048 && openssl rsa -pubout -in EXAMPLE.key -out EXAMPLE.pub
```
### Step 2: Create a JIRA Application Link
@@ -149,7 +152,7 @@ node -p -e 'JSON.stringify(require("fs").readFileSync("EXAMPLE.key").toString("a
"queryString": [],
"postData": {
"mimeType": "application/json",
- "text": "{ \"name\": \"jira\", \"strategy\": \"oauth1\", \"options\": { \"consumerKey\", \"CONSUMER_KEY\", \"consumerSecret\": \"CONSUMER_SECRET\", \"requestTokenURL\": \"JIRA_URL/plugins/servlet/oauth/request-token\", \"accessTokenURL\": \"JIRA_URL/plugins/servlet/oauth/access-token\", \"userAuthorizationURL\": \"JIRA_URL/plugins/servlet/oauth/authorize\", \"signatureMethod\": \"RSA-SHA1\", \"scripts\": { \"fetchUserProfile\": \"function(token, tokenSecret, ctx, cb) {\n // Based on passport-atlassian-oauth\n // https://github.com/tjsail33/passport-atlassian-oauth/blob/a2e444b0c3969dfd7caf4524ce4a4c379656ba2e/lib/passport-atlassian-oauth/strategy.js\n var jiraUrl = 'JIRA_URL';\n var OAuth = new require('oauth').OAuth;\n var oauth = new OAuth(ctx.requestTokenURL, ctx.accessTokenURL, ctx.client_id, ctx.client_secret, '1.0', null, 'RSA-SHA1');\n function oauthRequest(url, cb) {\n return oauth._performSecureRequest(token, tokenSecret, 'GET', url, null, '', 'application/json', cb);\n }\n oauthRequest(jiraUrl + '/rest/auth/1/session', function(err, body, res) {\n if (err) return cb(err);\n if (res.statusCode !== 200) return cb(new Error('StatusCode: ' + r.statusCode));\n var json;\n try {\n json = JSON.parse(body);\n } catch(ex) {\n return cb(new Error('Invalid JSON returned from JIRA', ex));\n }\n var profileUrl = jiraUrl + '/rest/api/2/user?expand=groups&username=' + encodeURIComponent(json.name);\n oauthRequest(profileUrl, function(err, body, res) {\n if (err) return cb(err);\n if (res.statusCode !== 200) return cb(new Error('StatusCode: ' + r.statusCode));\n try {\n json = JSON.parse(body);\n } catch(ex) {\n return cb(new Error('Invalid JSON returned from JIRA', ex));\n }\n // Auth0-specific mappings, customize as n:qeeded\n // https:///user-profile/normalized\n return cb(null, {\n user_id: json.name,\n username: json.name,\n email: json.emailAddress,\n name: json.displayName,\n groups: json.groups,\n picture: json.avatarUrls['48x48'],\n active: json.active,\n self: json.self,\n timezone: json.timeZone,\n locale: json.locale\n });\n });\n });\n}\n"
+ "text": "{ \"name\": \"jira\", \"strategy\": \"oauth1\", \"options\": { \"consumerKey\", \"CONSUMER_KEY\", \"consumerSecret\": \"CONSUMER_SECRET\", \"requestTokenURL\": \"JIRA_URL/plugins/servlet/oauth/request-token\", \"accessTokenURL\": \"JIRA_URL/plugins/servlet/oauth/access-token\", \"userAuthorizationURL\": \"JIRA_URL/plugins/servlet/oauth/authorize\", \"signatureMethod\": \"RSA-SHA1\", \"scripts\": { \"fetchUserProfile\": \"function(token, tokenSecret, ctx, cb) {\n // Based on passport-atlassian-oauth\n // https://github.com/tjsail33/passport-atlassian-oauth/blob/a2e444b0c3969dfd7caf4524ce4a4c379656ba2e/lib/passport-atlassian-oauth/strategy.js\n var jiraUrl = 'JIRA_URL';\n var OAuth = new require('oauth').OAuth;\n var oauth = new OAuth(ctx.requestTokenURL, ctx.accessTokenURL, ctx.client_id, ctx.client_secret, '1.0', null, 'RSA-SHA1');\n function oauthRequest(url, cb) {\n return oauth._performSecureRequest(token, tokenSecret, 'GET', url, null, '', 'application/json', cb);\n }\n oauthRequest(jiraUrl + '/rest/auth/1/session', function(err, body, res) {\n if (err) return cb(err);\n if (res.statusCode !== 200) return cb(new Error('StatusCode: ' + r.statusCode));\n var json;\n try {\n json = JSON.parse(body);\n } catch(ex) {\n return cb(new Error('Invalid JSON returned from JIRA', ex));\n }\n var profileUrl = jiraUrl + '/rest/api/2/user?expand=groups&username=' + encodeURIComponent(json.name);\n oauthRequest(profileUrl, function(err, body, res) {\n if (err) return cb(err);\n if (res.statusCode !== 200) return cb(new Error('StatusCode: ' + r.statusCode));\n try {\n json = JSON.parse(body);\n } catch(ex) {\n return cb(new Error('Invalid JSON returned from JIRA', ex));\n }\n // Auth0-specific mappings, customize as n:qeeded\n // https:///users/normalized\n return cb(null, {\n user_id: json.name,\n username: json.name,\n email: json.emailAddress,\n name: json.displayName,\n groups: json.groups,\n picture: json.avatarUrls['48x48'],\n active: json.active,\n self: json.self,\n timezone: json.timeZone,\n locale: json.locale\n });\n });\n });\n}\n"
},
"headersSize": -1,
"bodySize": -1,
diff --git a/articles/connections/how-to-test-partner-connection.md b/articles/connections/how-to-test-partner-connection.md
index 87784c9734..21359c8e7c 100644
--- a/articles/connections/how-to-test-partner-connection.md
+++ b/articles/connections/how-to-test-partner-connection.md
@@ -1,9 +1,14 @@
---
-description: How to test a partner connection.
+description: Learn how to test a partner connection.
+topics:
+ - connections
+ - troubleshooting
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Testing a partner connection
-
-Testing a connection in Auth0 is very easy:
+# Test Partner Connections
1. Click on the __Try__ button on each connection.
1. Login with the identity provider.
@@ -11,35 +16,33 @@ Testing a connection in Auth0 is very easy:
Auth0 simulates the authentication flow as if it was an application, displaying the __User Profile__ resulting from a successful authentication.
-There's a caveat though: for this to work you have to be logged-in in the dashboard.
-
-This is often not possible if you are testing a connection that belongs to someone else, and you don't have test credentials with them. This is common when connecting to __Enterprise connections__ such as __SAML IdPs__ or __Active Directory__.
+There's a caveat though: for this to work you have to be logged in to the Auth0 Dashboard.
-Having your partners test the new connection is very easy nevertheless:
+This is often not possible if you are testing a connection that belongs to someone else, and you don't have test credentials with them. This is common when connecting to __Enterprise connections__ such as __SAML IdPs__ or __Active Directory__.
-## 1. Create a Test app
+Your partners can test the new connection.
-To register a new application on Auth0 go to [Dashboard > Applications > Create](${manage_url}/#/applications/create). You can give it any name, for example, `Test App`.
+1. Register a test app.
-In the settings of the newly created app, configure __Allowed Callback Urls__ to `http://jwt.io`.
+ - Navigate to [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications), and click **Create Application**. You can give it any name, for example, `Test App`.
-Click on __SAVE CHANGES__.
+ - In the settings of the newly-created app, configure __Allowed Callback Urls__ to `http://jwt.io`.
-## 2. Send your Partner the link to login
+ - Select __Save Changes__.
-```text
-https://${account.namespace}/authorize?response_type=token&scope=openid%20profile&client_id=${account.clientId}&redirect_uri=http://jwt.io&connection=THE_CONNECTION_YOU_WANT_TO_TEST
-```
+2. Send your partner the link to log in.
-Make sure you replace these two parameters:
+ ```text
+ https://${account.namespace}/authorize?response_type=token&scope=openid%20profile&client_id=${account.clientId}&redirect_uri=http://jwt.io&connection=THE_CONNECTION_YOU_WANT_TO_TEST
+ ```
-* __client_id__: the app client_id created in __Step 1__.
-* __connection__: the name of the connection you want to test.
+ Replace these two parameters:
-## 3. Test it
+ * __client_id__: the app client_id created in __Step 1__.
+ * __connection__: the name of the connection you want to test.
-When your partner follows the link above, they will be redirected to their configured Identity Provider (the __connection__). After successful authentication, they will be sent back to [JWT.io](http://jwt.io) where all user properties will be decoded from the token.
+3. Test the connection. When your partner follows the link, they will be redirected to their configured Identity Provider (the __connection__). After successful authentication, they will be sent back to [JWT.io](http://jwt.io) where all user properties will be decoded from the token.
::: note
-Note that the test app is not a _real_ app. [JWT.io](http://jwt.io) is just a testing website that is able to decode tokens sent on a URL fragment.
+The test app is not a _real_ app. [JWT.io](http://jwt.io) is a testing website that decodes tokens sent on a URL fragment.
:::
\ No newline at end of file
diff --git a/articles/connections/index.md b/articles/connections/index.md
index f728a4e17f..6efe88df28 100644
--- a/articles/connections/index.md
+++ b/articles/connections/index.md
@@ -1,61 +1,31 @@
---
-url: /identityproviders
-description: Auth0 is an identity hub that supports the many authentication providers listed here.
+section: articles
+classes: topic-page
+title: Connections
+description: Describes the various sources of users supported by Auth0, including identity providers, databases, and passwordless authentication methods.
+topics:
+ - connections
+contentType:
+ - index
+useCase:
+ - customize-connections
+ - add-idp
---
+# Connections
-# Identity Providers Supported by Auth0
+A connection is the relationship between Auth0 and a source of users, which may include external Identity Providers (such as Google or LinkedIn), databases, or passwordless authentication methods. Auth0 sits between your application and its sources of users, which adds a level of abstraction, so your application is isolated from any changes to and idiosyncrasies of each source's implementation.
-An Identity Provider is a server that can provide identity information to other servers. For example, Google is an Identity Provider. If you log in to a site using your Google account, then a Google server will send your identity information to that site.
+By default, Auth0 automatically syncs user profile data with each user login, thereby ensuring that changes made in the connection source are automatically updated in Auth0. You can disable synchronization to allow for updating profile attributes from your application.
-Auth0 is an identity hub that supports many identity providers using various protocols (like [OpenID Connect](/protocols/oidc), [SAML](/protocols/saml), [WS-Federation](/protocols/ws-fed), and more).
+You can configure any number of connections for your applications.
-Auth0 sits between your app and the Identity Provider that authenticates your users. This adds a level of abstraction so your app is isolated from any changes to and idiosyncrasies of each provider's implementation.
-
-The relationship between Auth0 and any of these authentication providers is referred to as a **connection**. Auth0 supports [Social](#social), [Enterprise](#enterprise), [Database](#database-and-custom-connections) and [Passwordless](#passwordless) connections.
-
-## Social
-
-Auth0 supports the following social providers out of the box. You can also use any [OAuth2 Authorization Server](/connections/social/oauth2).
-
-<% var socialConnections = cache.find('articles/connections/social', {sort: 'index'}); %>
-<%= include('./_connections', { connections: socialConnections }) %>
-
-## Enterprise
-
-<% var enterpriseConnections = cache.find('articles/connections/enterprise', {sort: 'index'}); %>
-<%= include('./_connections', { connections: enterpriseConnections }) %>
-
-## Legal Identities
-
-Through our partner, Criipto, we offer a growing range of government and bank identities tied to legal persons.
-<% var criiptoConnections = cache.find('articles/connections/criipto', {sort: 'index'}); %>
-<%= include('./_connections', { connections: criiptoConnections }) %>
-
-If the one you need isn't found here, we suggest getting in touch with [Criipto](https://criipto.com).
-
-## Database and Custom Connections
-
-If you want to create your own user store, instead of using external identity providers like Google or Facebook, you can use a Database Connection. This way you can authenticate users with an email or username and a password. The credentials can be securely stored either in the Auth0 user store or in your own database.
-
-You can create any number of custom fields and store this information as part of the `user_metadata`. You can easily import users from a legacy user store, enable or disable sign ups, configure your password policy, or enable Multifactor Authentication.
-
-For more details, refer to the [Database Connections](/connections/database) documentation.
-
-## Passwordless
-
-Full documentation on Passwordless authentication can be found at the links below:
-
-
+| Read... | To learn... |
+|---------|-------------|
+| [Social Identity Providers](/connections/identity-providers-social) | About the external social Identity Providers supported by Auth0. |
+| [Enterprise Identity Providers](/connections/identity-providers-enterprise) | About the external enterprise Identity Providers supported by Auth0. |
+| [Legal Identity Providers](/connections/identity-providers-legal) | About the external legal Identity Providers supported by Auth0. |
+| [Database Connections](/connections/database) | How to create your own user store, which allows you to authenticate users with an email address or username and a password. The credentials can be stored securely in either the Auth0 user store or your own database. |
+| [Passwordless Connections](/connections/passwordless) | How to allow users to log in without needing to remember a password. Users enter their mobile phone number or email address, and receive a one-time code or link, which they can use to log in. |
+| [View Connections](/dashboard/guides/connections/view-connections) | How to view the configure connections for your application using the Auth0 Dashboard. |
+| [Disable Connection Sync](/dashboard/guides/connections/configure-connection-sync) | How to disable the synchronization between user profile data and the connection source, which allows you to update profile attributes from your application instead. |
+| [Pass Parameters to Identity Providers](/connections/pass-parameters-to-idps) | How to pass provider-specific parameters to an Identity Provider during authentication. |
\ No newline at end of file
diff --git a/articles/connections/legal.md b/articles/connections/legal.md
new file mode 100644
index 0000000000..cb14347513
--- /dev/null
+++ b/articles/connections/legal.md
@@ -0,0 +1,18 @@
+---
+title: Legal Identity Providers
+description: Learn about legal identity providers supported by Auth0.
+topics:
+ - connections
+ - identity-providers
+contentType:
+ - reference
+useCase:
+ - customize-connections
+ - add-idp
+---
+# Legal Identity Providers
+
+Through our partner, Criipto, we offer a growing range of government and bank identities tied to legal persons. If what you need isn't found here, please contact [Criipto](https://criipto.com).
+
+<% var criiptoConnections = cache.find('articles/connections/criipto', {sort: 'index'}); %>
+<%= include('./_connections', { connections: criiptoConnections }) %>
\ No newline at end of file
diff --git a/articles/connections/options-mgmt-api.md b/articles/connections/options-mgmt-api.md
new file mode 100644
index 0000000000..15a15a88ae
--- /dev/null
+++ b/articles/connections/options-mgmt-api.md
@@ -0,0 +1,33 @@
+---
+title: Connection Options in the Management API
+description: Describes the options attributes used when creating or updating a connection using the Management API.
+topics:
+ - connections
+ - mgmt-api
+contentType: reference
+useCase: add-login
+---
+# Connection Options in the Management API
+
+When creating or updating a connection in the Management API, you can include a variety of custom options in the `options` attribute, such as a password strength for the connection or provider-specific parameters to pass to an Identity Provider.
+
+The following elements are available for the `options` attribute. These are optional when calling the [Create a Connection endpoint](/api/management/v2#!/Connections/post_connections) or [Update a Connection endpoint](/api/management/v2#!/Connections/patch_connections_by_id).
+
+| Element | Type | Description |
+|-|-|-|
+| `validation` | object | <%= include('./_includes/_options-validation.md') %> Used with [database connections](/connections/database). |
+| `passwordPolicy` | string | The strength level of the password. Allowed values include `none`, `low`, `fair`, `good`, and `excellent`. Used with [database connections](/connections/database). |
+| `password_complexity_options` | object | <%= include('./_includes/_options-prop-pw-complexity.md') %> Used with [database connections](/connections/database). |
+| `password_history` | object | <%= include('./_includes/_options-prop-pw-history.md') %> Used with [database connections](/connections/database). |
+| `password_no_personal_info` | object | <%= include('./_includes/_options-prop-pw-no-pers-info.md') %> Used with [database connections](/connections/database). |
+| `password_dictionary` | object | <%= include('./_includes/_options-prop-pw-dictionary.md') %> Used with [database connections](/connections/database). |
+| `basic_profile` | boolean | Indicates that you want basic profile information (email address and email verified flag) stored in the Auth0 User Profile. Used with social and enterprise connections. |
+| `ext_profile` | boolean | Indicates that you want extended profile information (name, public profile URL, photo, gender, birthdate, country, language, and timezone) stored in the Auth0 User Profile. Used with social and enterprise connections. |
+| `ext_admin` | boolean | Indicates that you want to store whether or not the user is a domain administrator. Used with enterprise connections. |
+| `ext_is_suspended` | boolean | Indicates that you want to store whether or not a user's account is suspended. Used with enterprise connections. |
+| `ext_agreed_terms` | boolean | Indicates that you want to store whether or not a user has agreed to the terms of service. Used with enterprise connections. |
+| `ext_groups` | boolean | Indicates that you want to store the distribution list(s) to which a user belongs. Used with enterprise connections. |
+| `ext_assigned_plans` | boolean | Indicates that you want to store a list of the Office 365 assigned plans for the user. Used with the Office 365 enterprise connection, which is deprecated; these connections should be [migrated to Azure AD connections](/integrations/office365-connection-deprecation-guide). |
+| `api_enable_users` | boolean | When enabled, allows users to make calls to the Google Directory API. Used with enterprise connections. |
+| `upstream_params` | object | <%= include('./_includes/_options-upstream-params.md') %> Used with connections that use [Identity Providers](/connections). |
+| `requires_username` | boolean | Indicates whether or not a user must provide a username in addition to their email address. |
diff --git a/articles/connections/pass-parameters-to-idps.md b/articles/connections/pass-parameters-to-idps.md
new file mode 100644
index 0000000000..e967f8d79d
--- /dev/null
+++ b/articles/connections/pass-parameters-to-idps.md
@@ -0,0 +1,165 @@
+---
+title: Pass Parameters to Identity Providers
+description: How to pass parameters to an Identity Provider API
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+# Pass Parameters to Identity Providers
+
+You can pass provider-specific parameters to an Identity Provider during authentication. The values can either be static per connection or dynamic per user. Note the following restrictions:
+
+- Only [valid OAuth 2.0/OIDC parameters](http://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint) are accepted.
+- Not all Identity Providers support upstream parameters. Check with the specific Identity Provider before you proceed with your implementation.
+- SAML identity providers, in particular, do not support upstream parameters.
+
+## Static parameters
+
+You can configure static parameters per connection with the Connections endpoints of our [Management API](/api/management/v2). Each time your connection is used, the specified parameters will be sent to the Identity Provider.
+
+When you [create](/api/management/v2#!/Connections/post_connections) or [update](/api/management/v2#!/Connections/patch_connections_by_id) a connection, use the `upstream_params` element of the `options` attribute.
+
+### Example: WordPress
+As an example, let's use WordPress, which allows you to pass an optional `blog` parameter to its OAuth 2.0 authorization endpoint (for more information, see [WordPress's OAuth 2.0 documentation](https://developer.wordpress.com/docs/oauth2/)).
+
+Let's assume that you have a working WordPress connection and you want to always request that users have access to the `myblog.wordpress.com` blog when logging in with it. To do this, assign WordPress's `blog` parameter a default value of `myblog.wordpress.com`.
+
+First, we will use the [Get Connection](/api/management/v2#!/Connections/get_connections_by_id) endpoint, to retrieve the existing values of the `options` object. This is mandatory since the [Update Connection](/api/management/v2#!/Connections/patch_connections_by_id) endpoint, which we will use next, overrides this object will be overridden, so if parameters are missing they will be lost after the update.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/connections/YOUR-WORDPRESS-CONNECTION-ID",
+ "headers": [
+ {
+ "name": "Authorization",
+ "value": "Bearer YOUR_ACCESS_TOKEN"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+}
+```
+
+Let's say that the `options` contents for our wordpress connection are the following:
+
+```text
+{
+ "options": {
+ "client_id": "",
+ "profile": true,
+ "scope": ["profile"]
+ }
+}
+```
+
+Now we can send the update request, copying the existing `options` contents and adding also the `blog` parameter.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/connections/YOUR-WORDPRESS-CONNECTION-ID",
+ "headers": [
+ {
+ "name": "Authorization",
+ "value": "Bearer YOUR_ACCESS_TOKEN"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"options\":{\"client_id\":\"\",\"profile\":true,\"scope\":[\"profile\"],\"upstream_params\":{\"blog\":{\"value\":\"myblog.wordpress.com\"}}}}"
+ }
+}
+```
+
+Now every time a user authenticates with this connection the request to Wordpress will include the query parameter `blog=myblog.wordpress.com`.
+
+## Dynamic parameters
+
+You can configure upstream parameters per user. This way when a user authenticates, the parameters will be dynamically added to the authorization query.
+
+To do this, use the `upstream_params` element of the `options` attribute to specify a mapping between one of the existing accepted parameters to the parameter accepted by the Identity Provider.
+
+### Field list
+
+Here are fields available for the `enum` parameter:
+
+* `acr_values`
+* `audience`
+* `client_id`
+* `display`
+* `id_token_hint`
+* `login_hint`
+* `max_age`
+* `prompt`
+* `resource`
+* `response_mode`
+* `response_type`
+* `ui_locales`
+
+### Example: Twitter
+
+As an example, let's use Twitter, which allows you to pass an optional `screen_name` parameter to its OAuth authorization endpoint (for more information, see [Twitter's API reference](https://developer.twitter.com/en/docs/basics/authentication/api-reference/authorize)).
+
+To continue, you should already have a working Twitter connection; to learn how to configure one, see [Connect Your App to Twitter](/connections/social/twitter).
+
+Twitter's `screen_name` parameter pre-fills the username input box of the login screen with the given value, so we want to map it to the existing accepted parameter of `login_hint`.
+
+Let's assume that you already retrieved the contents of the `options` object (like we did in the previous paragraph) and they are the following:
+
+```text
+"options": {
+ "client_id": "thisismyid",
+ "client_secret": "thisismysecret",
+ "profile": true
+}
+```
+
+Send the update request, copying the existing `options` contents and adding also the `screen_name` parameter.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/connections/YOUR-TWITTER-CONNECTION-ID",
+ "headers": [
+ {
+ "name": "Authorization",
+ "value": "Bearer YOUR_ACCESS_TOKEN"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"options\": {\"client_id\": \"thisismyid\", \"client_secret\": \"thisismysecret\", \"profile\": true, \"upstream_params\": {\"screen_name\": {\"alias\": \"login_hint\"}}}}"
+ }
+}
+```
+
+Now, when you call the [Authorize endpoint](/api/authentication#authorize-application) for a specific user, you can pass their email address in the `login_hint` parameter.
+
+```text
+https://${account.namespace}/authorize
+ ?client_id=${account.clientId}
+ &response_type=token
+ &redirect_uri=${account.callback}
+ &scope=openid%20name%20email
+ &login_hint=john@gmail.com
+```
+
+And that value will in turn be passed along to the Twitter authorization endpoint in the `screen_name` parameter.
+
+```text
+https://api.twitter.com/oauth/authorize
+ ?oauth_token=YOUR_TOKEN
+ &screen_name=john@gmail.com
+```
diff --git a/articles/connections/passwordless/_includes/_introduction-email-magic-link.md b/articles/connections/passwordless/_includes/_introduction-email-magic-link.md
new file mode 100644
index 0000000000..88b93e7aad
--- /dev/null
+++ b/articles/connections/passwordless/_includes/_introduction-email-magic-link.md
@@ -0,0 +1,10 @@
+
+With an email connection, the user is asked to enter their email address, to which Auth0 usually sends a one-time-use code. Instead, you can configure Auth0 to send a magic link. If you are using Universal Login, make sure you [configure Universal Login with Passwordless](/dashboard/guides/universal-login/configure-login-page-passwordless).
+
+
+
+
+
+The user then clicks the button or link in the email and is automatically signed in to your application.
+
+
diff --git a/articles/connections/passwordless/_includes/_introduction-email.md b/articles/connections/passwordless/_includes/_introduction-email.md
new file mode 100644
index 0000000000..45009e0d1e
--- /dev/null
+++ b/articles/connections/passwordless/_includes/_introduction-email.md
@@ -0,0 +1,10 @@
+When Passwordless is configured to use Email. the user is asked to enter their email address, to which Auth0 sends a one-time-use code. The user then enters the code into your application. If you are using Universal Login, make sure you [configure Universal Login with Passwordless](/dashboard/guides/universal-login/configure-login-page-passwordless).
+
+If the email address attached to the code matches an existing user, Auth0 authenticates the user:
+
+
+
+If the user is new, their user profile is created for the `email` connection before they are authenticated by Auth0.
+
+
+
diff --git a/articles/connections/passwordless/_includes/_introduction-sms.md b/articles/connections/passwordless/_includes/_introduction-sms.md
new file mode 100644
index 0000000000..c9fc26970c
--- /dev/null
+++ b/articles/connections/passwordless/_includes/_introduction-sms.md
@@ -0,0 +1,11 @@
+With an SMS connection, the user is asked to enter a phone number. By default, Auth0 uses [Twilio](https://www.twilio.com) to send a one-time-use code to that phone number. (If you have a custom SMS gateway, you can [modify your connection to use that instead of Twilio](/connections/passwordless/use-sms-gateway-passwordless).)
+
+The user then enters the code into your application. If you are using Universal Login, make sure you [configure Universal Login with Passwordless](/dashboard/guides/universal-login/configure-login-page-passwordless).
+
+If the phone number attached to the code matches an existing user, Auth0 authenticates the user:
+
+
+
+If the user is new, their user profile is created for the `sms` connection before they are authenticated by Auth0.
+
+
diff --git a/articles/connections/passwordless/_includes/_rate_limit_server_side.md b/articles/connections/passwordless/_includes/_rate_limit_server_side.md
new file mode 100644
index 0000000000..29a8815a31
--- /dev/null
+++ b/articles/connections/passwordless/_includes/_rate_limit_server_side.md
@@ -0,0 +1,4 @@
+
+## Setting the `auth0-forwarded-for` header for rate-limit purposes
+
+The `/passwordless/start` endpoint has a [rate limit](/policies/rate-limits#authentication-api) of 50 requests per hour per IP. If you call the API from the server-side, your backend's IP may easily hit these rate limits. To address this issue read more here about [rate limiting in passwordless endpoints](/connections/passwordless/relevant-api-endpoints#rate-limiting-in-passwordless-endpoints).
diff --git a/articles/connections/passwordless/_includes/_setup-cors.md b/articles/connections/passwordless/_includes/_setup-cors.md
new file mode 100644
index 0000000000..a2d3a95518
--- /dev/null
+++ b/articles/connections/passwordless/_includes/_setup-cors.md
@@ -0,0 +1,7 @@
+### Configure Cross-Origin Resource Sharing (CORS)
+
+For security purposes, your app's origin URL must be listed as an approved URL. If you have not already added it to the **Allowed Callback URLS** for your application, you will need to add it to the list of **Allowed Origins (CORS)**.
+
+1. Navigate to [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications), and select the name of your application to see its settings.
+
+2. Locate **Allowed Origins (CORS)**, enter your application's [origin URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin), and select **Save Changes**.
diff --git a/articles/connections/passwordless/_includes/_setup-email.md b/articles/connections/passwordless/_includes/_setup-email.md
new file mode 100644
index 0000000000..705f028170
--- /dev/null
+++ b/articles/connections/passwordless/_includes/_setup-email.md
@@ -0,0 +1,80 @@
+
+## Configure the connection
+
+1. Navigate to [Auth0 Dashboard > Authentication > Passwordless](${manage_url}/#/connections/passwordless), and enable the **Email** switch.
+
+
+
+2. Select your **Email Syntax**, and enter your email's **From**, **Subject**, and **Message** text.
+
+
+
+::: note
+You must change the **From** value to a non **@auth0.com** address for your custom email to be sent. Otherwise the default email template will be sent.
+:::
+
+3. Enter any **Authentication Parameters** you would like to include in the generated sign-in link.
+
+4. Adjust settings for your **OTP Expiry** and **OTP Length**
+
+<%= include('../../_otp-limitations') %>
+
+5. Decide if you want to **Disable Signups**. You can enable passwordless access just for existing users by enabling this setting.
+
+### Multi-language support
+
+The **Message** area supports multiple languages.
+
+To choose the language, call the [/passwordless/start authentication endpoint](/api/authentication/reference#get-code-or-link) and set the value of the 'x-request-language' header. When this header is not set, the language is extracted from the 'accept-language' header, which is automatically set by the browser.
+
+### Message syntax
+
+The **Message** area accepts Liquid syntax. You can use this syntax, combined with exposed parameter values, to programmatically construct elements of the message. For example, you can reference the `request_language` parameter to change the language of the message:
+
+```text
+{% if request_language contains 'dutch' %}
+ Hier is uw verificatie code: {{ code }}
+{% endif %}
+
+{% if request_language contains 'fr-FR' %}
+ Ceci est votre code: {{ code }}
+{% endif %}
+```
+
+The following parameters are available when defining the message template:
+
+| Exposed Parameter | Description |
+|:------------------|:---------|
+| `code` | The password to use |
+| `link` | The generated sign-in link |
+| `application.name` | The name of the application with which the user is signing up |
+| `request_language` | The requested language for message content |
+| `operation` | Indicates when the template has been triggered by an update to a user's email via the API. Equals `change_email` when triggered; otherwise, null.|
+
+## Enable your apps
+
+Select the **Applications** view, and enable the applications for which you would like to use Passwordless Email.
+
+## Email Providers
+
+By default, Auth0 sends the email from its own SMTP provider. Auth0's built-in email infrastructure should be used for testing-level emails only. You can [configure your own email provider](/email/providers) to better monitor and troubleshoot the email service as well as be able to fully customize the emails.
+
+::: note
+You will need to use your own email provider to be able to modify the `From`, `Subject`, and `Body` of Passwordless emails.
+:::
+
+You may configure Auth0 to send users one-time codes using:
+
+* [Mandrill](/email/providers#configure-mandrill)
+* [AWS](/email/providers#configure-amazon-ses)
+* [Twilio SendGrid](/email/providers#configure-sendgrid)
+* [SparkPost](/email/providers#configure-sparkpost)
+* [Mailgun](/email/providers#configure-mailgun)
+* [your own custom SMTP email provider](/email/providers#configure-a-custom-smtp-server)
+
+::: note
+To use a custom SMTP email provider, the SMTP server must:
+* support LOGIN authentication
+* support TLS 1.0 or higher
+* use a certificate signed by a public certificate authority (CA)
+:::
diff --git a/articles/connections/passwordless/_includes/_setup-sms-twilio.md b/articles/connections/passwordless/_includes/_setup-sms-twilio.md
new file mode 100644
index 0000000000..cd5bc9e769
--- /dev/null
+++ b/articles/connections/passwordless/_includes/_setup-sms-twilio.md
@@ -0,0 +1,77 @@
+
+Navigate to [Auth0 Dashboard > Authentication > Passwordless](${manage_url}/#/connections/passwordless), and enable the **SMS** switch.
+
+
+
+To send the SMS, you can either use Twilio, or a Custom SMS Gateway.
+
+### Configure Twilio settings
+
+You will need a [Twilio Account SID](https://www.twilio.com/help/faq/twilio-basics/what-is-an-application-sid) and a [Twilio Auth Token](https://www.twilio.com/help/faq/twilio-basics/what-is-the-auth-token-and-how-can-i-change-it). These are the Twilio API credentials that Auth0 will use to send an SMS to the user.
+
+1. Enter your **Twilio Account SID** and **Twilio Auth Token**.
+
+::: note
+To learn how to find your Twilio SID and Auth Token, see Twilio docs: [How to create an Application SID](https://www.twilio.com/help/faq/twilio-basics/what-is-an-application-sid) and [Auth Tokens and how to change them](https://www.twilio.com/help/faq/twilio-basics/what-is-the-auth-token-and-how-can-i-change-it).
+:::
+
+
+
+2. Select your **SMS Source** and depending on your selection, enter either your **Twilio Messaging Service SID** or a **From** phone number. Users will see what you enter as the sender of the SMS.
+
+::: note
+To learn about using Twilio Messaging Services, see Twilio docs: [Sending Messages with Messaging Services](https://www.twilio.com/docs/sms/services/services-send-messages).
+:::
+
+### Configure a custom SMS gateway
+
+If you would like to use your own SMS gateway, you will need to create the passwordless connection and then modify it using our Management API. To learn how to modify the connection to use your own SMS gateway, see [Configure SMS Gateway for Passwordless Connections](/connections/passwordless/use-sms-gateway-passwordless).
+
+### Configure passwordless SMS settings
+
+1. In **Message**, enter the body text of the SMS.
+
+::: note
+The `@@password@@` placeholder will automatically be replaced with the one-time password that is sent to the user.
+:::
+
+2. Adjust settings for your **OTP Expiry** and **OTP Length**.
+
+<%= include('../../_otp-limitations') %>
+
+3. Decide if you want to **Disable Signups**. You can enable passwordless access just for existing users by enabling this setting.
+
+4. Click **Save**.
+
+#### Multi-language support
+
+The **Message** area supports multiple languages.
+
+To choose the language, call the [/passwordless/start authentication endpoint](/api/authentication/reference#get-code-or-link) and set the value of the 'x-request-language' header. When this header is not set, the language is extracted from the 'accept-language' header, which is automatically set by the browser.
+
+#### Message syntax
+
+The **Message** area accepts Liquid syntax. You can use this syntax, combined with exposed parameter values, to programmatically construct elements of the message. For example, you can reference the `request_language` parameter to change the language of the message:
+
+```text
+{% if request_language contains 'dutch' %}
+ Hier is uw verificatie code: {{ password }}
+{% endif %}
+
+{% if request_language contains 'fr-FR' %}
+ Ceci est votre code: {{ password }}
+{% endif %}
+```
+
+The following parameters are available when defining the message template:
+
+| Exposed Parameter | Description |
+|:------------------|:---------|
+| `password` or `code` | The password to use |
+| `phone_number` | The user's phone number |
+| `application.name` | The name of the application with which the user is signing up |
+| `request_language` | The requested language for message content |
+
+### Enable your apps
+
+Select the **Applications** view, and enable the applications for which you would like to use Passwordless SMS.
diff --git a/articles/connections/passwordless/_init-passwordless-lock.md b/articles/connections/passwordless/_init-passwordless-lock.md
deleted file mode 100644
index f69882d3fe..0000000000
--- a/articles/connections/passwordless/_init-passwordless-lock.md
+++ /dev/null
@@ -1,3 +0,0 @@
-Lock with Passwordless Mode is a professional-looking dialog that allows users to log in after receiving a one-time password via email or text message.
-
-After installing [Lock](/libraries/lock) (version 11.2.0 or later), you must initialize it with your `Client Id` and `domain`. You can find this information in the Dashboard on your [application settings](${manage_url}/#/applications/${account.clientId}/settings) page.
diff --git a/articles/connections/passwordless/_introduction-email-magic-link.md b/articles/connections/passwordless/_introduction-email-magic-link.md
deleted file mode 100644
index cd442cf0b5..0000000000
--- a/articles/connections/passwordless/_introduction-email-magic-link.md
+++ /dev/null
@@ -1,11 +0,0 @@
-Instead of sending the user a one time code, you can configure Auth0 to send a magic link:
-
-
-
-Auth0 will send an email containing a clickable button or link:
-
-
-
-After clicking the button, the user will be automatically signed-in to your application:
-
-
\ No newline at end of file
diff --git a/articles/connections/passwordless/_introduction-email.md b/articles/connections/passwordless/_introduction-email.md
deleted file mode 100644
index a268399543..0000000000
--- a/articles/connections/passwordless/_introduction-email.md
+++ /dev/null
@@ -1,13 +0,0 @@
-With the e-mail connection, the user is requested to enter their e-mail address. Auth0 then sends an email to that address containing a one-time code.
-
-Once the user enters this code into your application, a new user will be created in the `email` connection. The user is then authenticated by Auth0.
-
-
-
-If the e-mail address matches an existing user, Auth0 just authenticates the user:
-
-
-
-<% if (isMobile) { %>
-On mobile platforms, your application will receive an `id_token`, the user profile and, optionally, a `refresh_token`.
-<% } %>
\ No newline at end of file
diff --git a/articles/connections/passwordless/_introduction-lock.md b/articles/connections/passwordless/_introduction-lock.md
deleted file mode 100644
index 3295a82e18..0000000000
--- a/articles/connections/passwordless/_introduction-lock.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The [Lock](https://github.com/auth0/${repository}/) is a widget that allows you to easily integrate Auth0's Passwordless Authentication into your ${platform} applications.
-
-After [installing and configuring](/libraries/${docsUrl}#install) ${repository} you will be able to use Lock as follows.
diff --git a/articles/connections/passwordless/_introduction-sms.md b/articles/connections/passwordless/_introduction-sms.md
deleted file mode 100644
index b22bb8f4a7..0000000000
--- a/articles/connections/passwordless/_introduction-sms.md
+++ /dev/null
@@ -1,13 +0,0 @@
-With the SMS connection, the user is requested to enter a phone number. Auth0 then uses [Twilio](http://www.twilio.com) to send a one time code to that number.
-
-Once the user enters this code into your application, a new user will be created in the `sms` connection. The user is then authenticated by Auth0.
-
-
-
-If the phone number matches an existing user, Auth0 just authenticates the user:
-
-
-
-<% if (isMobile) { %>
-On mobile platforms, your application will receive an `id_token`, the user profile and, optionally, a `refresh_token`.
-<% } %>
\ No newline at end of file
diff --git a/articles/connections/passwordless/_introduction.md b/articles/connections/passwordless/_introduction.md
deleted file mode 100644
index 4a50ef1895..0000000000
--- a/articles/connections/passwordless/_introduction.md
+++ /dev/null
@@ -1,13 +0,0 @@
-Passwordless connections in Auth0 allow users to login without the need to remember a password.
-
-This improves the user experience, especially on mobile applications, since users will only need an email address or phone number to register for your application.
-
-Without passwords, your application will not need to implement a password reset procedure and users avoid the insecure practice of using the same password for many purposes.
-
-In addition, the credential used for authentication is automatically validated since the user just entered it at sign-up.
-
-## Configuration
-
-These connections use an authentication channel like SMS or email. Each of these channels can be configured in the dashboard under [Connections > Passwordless](${manage_url}/#/connections/passwordless).
-
-
\ No newline at end of file
diff --git a/articles/connections/passwordless/_old/_includes/_call-from-client-side.md b/articles/connections/passwordless/_old/_includes/_call-from-client-side.md
new file mode 100644
index 0000000000..6a630739ba
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_call-from-client-side.md
@@ -0,0 +1,3 @@
+:::warning
+Passwordless is designed to be called from the client-side and has a [rate limit](/policies/rate-limits#authentication-api) of 50 requests per hour per IP. If you call it from the server-side, your backend's IP may easily hit these rate limits.
+:::
\ No newline at end of file
diff --git a/articles/connections/passwordless/_old/_includes/_custom-domains.md b/articles/connections/passwordless/_old/_includes/_custom-domains.md
new file mode 100644
index 0000000000..b34b890b62
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_custom-domains.md
@@ -0,0 +1,3 @@
+::: note
+If you use custom domains, replace `${account.namespace}` with your custom domain.
+:::
diff --git a/articles/connections/passwordless/_email-controller-objc.md b/articles/connections/passwordless/_old/_includes/_email-controller-objc.md
similarity index 100%
rename from articles/connections/passwordless/_email-controller-objc.md
rename to articles/connections/passwordless/_old/_includes/_email-controller-objc.md
diff --git a/articles/connections/passwordless/_email-controller-swift.md b/articles/connections/passwordless/_old/_includes/_email-controller-swift.md
similarity index 100%
rename from articles/connections/passwordless/_email-controller-swift.md
rename to articles/connections/passwordless/_old/_includes/_email-controller-swift.md
diff --git a/articles/connections/passwordless/_email-login-objc.md b/articles/connections/passwordless/_old/_includes/_email-login-objc.md
similarity index 100%
rename from articles/connections/passwordless/_email-login-objc.md
rename to articles/connections/passwordless/_old/_includes/_email-login-objc.md
diff --git a/articles/connections/passwordless/_email-login-swift.md b/articles/connections/passwordless/_old/_includes/_email-login-swift.md
similarity index 100%
rename from articles/connections/passwordless/_email-login-swift.md
rename to articles/connections/passwordless/_old/_includes/_email-login-swift.md
diff --git a/articles/connections/passwordless/_email-send-code-objc.md b/articles/connections/passwordless/_old/_includes/_email-send-code-objc.md
similarity index 100%
rename from articles/connections/passwordless/_email-send-code-objc.md
rename to articles/connections/passwordless/_old/_includes/_email-send-code-objc.md
diff --git a/articles/connections/passwordless/_email-send-code-swift.md b/articles/connections/passwordless/_old/_includes/_email-send-code-swift.md
similarity index 100%
rename from articles/connections/passwordless/_email-send-code-swift.md
rename to articles/connections/passwordless/_old/_includes/_email-send-code-swift.md
diff --git a/articles/connections/passwordless/_init-auth0js.md b/articles/connections/passwordless/_old/_includes/_init-auth0js.md
similarity index 100%
rename from articles/connections/passwordless/_init-auth0js.md
rename to articles/connections/passwordless/_old/_includes/_init-auth0js.md
diff --git a/articles/connections/passwordless/_init-auth0js_v8.md b/articles/connections/passwordless/_old/_includes/_init-auth0js_v8.md
similarity index 100%
rename from articles/connections/passwordless/_init-auth0js_v8.md
rename to articles/connections/passwordless/_old/_includes/_init-auth0js_v8.md
diff --git a/articles/connections/passwordless/_init-auth0js_v9.md b/articles/connections/passwordless/_old/_includes/_init-auth0js_v9.md
similarity index 100%
rename from articles/connections/passwordless/_init-auth0js_v9.md
rename to articles/connections/passwordless/_old/_includes/_init-auth0js_v9.md
diff --git a/articles/connections/passwordless/_old/_includes/_init-passwordless-lock.md b/articles/connections/passwordless/_old/_includes/_init-passwordless-lock.md
new file mode 100644
index 0000000000..3c5dfa2ac4
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_init-passwordless-lock.md
@@ -0,0 +1,3 @@
+Lock with Passwordless Mode is a professional-looking dialog that allows users to log in after receiving a one-time password via email or text message.
+
+After installing [Lock](/libraries/lock) (version 11.2.0 or later), you must initialize it with your `Client Id` and `domain`. You can find this information at [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications) in your [application's settings](${manage_url}/#/applications/${account.clientId}/settings).
\ No newline at end of file
diff --git a/articles/connections/passwordless/_old/_includes/_introduction-lock.md b/articles/connections/passwordless/_old/_includes/_introduction-lock.md
new file mode 100644
index 0000000000..55f0f12293
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_introduction-lock.md
@@ -0,0 +1,3 @@
+[Lock](https://github.com/auth0/${repository}/) is a widget that allows you to easily integrate Auth0's Passwordless Authentication into your ${platform} applications.
+
+After [installing and configuring](/libraries/${docsUrl}#install) ${repository}, you will be able to use Lock as follows.
diff --git a/articles/connections/passwordless/_old/_includes/_introduction.md b/articles/connections/passwordless/_old/_includes/_introduction.md
new file mode 100644
index 0000000000..bc99aff991
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_introduction.md
@@ -0,0 +1,17 @@
+Passwordless connections in Auth0 allow users to login without the need to remember a password. The benefits of enabling passwordless connections include:
+
+* Improved user experience, particularly on mobile applications, since users only need an email address or phone number to sign up and the credential used for authentication is automatically validated after sign-up.
+
+* Enhanced security since users avoid the insecure practice of using the same password for many purposes.
+
+* Less effort for you since you will not need to implement a password reset procedure.
+
+## Configuration
+
+Passwordless connections use an authentication channel like SMS or email, which need to be configured at [Auth0 Dashboard > Authentication > Passwordless](${manage_url}/#/connections/passwordless).
+
+::: note
+We recommend implementing passwordless with Universal Login. If you are using embedded login with or Auth0.js, you will need to enable custom domains for your tenant. To learn more, see [Custom Domains](/custom-domains).
+:::
+
+
diff --git a/articles/connections/passwordless/_old/_includes/_setup-callback.md b/articles/connections/passwordless/_old/_includes/_setup-callback.md
new file mode 100644
index 0000000000..4f192283c3
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_setup-callback.md
@@ -0,0 +1,3 @@
+### Configure Callback URL
+
+For security purposes, you must add <% if(spa){ %>your page's URL<%} else {%>the callback URL<%}%> to the list of **Allowed callback URLs** in your application's settings at [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications).
\ No newline at end of file
diff --git a/articles/connections/passwordless/_old/_includes/_single-browser-magic-link.md b/articles/connections/passwordless/_old/_includes/_single-browser-magic-link.md
new file mode 100644
index 0000000000..1ad8e77cee
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_single-browser-magic-link.md
@@ -0,0 +1,5 @@
+::: note
+With magic link transactions, both the initial request and the response to the request must take place in the same browser or the transaction will fail. This is particularly relevant for iOS users, who cannot change their default web browser.
+
+For example, the user makes the request using Chrome, but iOS opens the magic link received via email using Safari. If this happens, the transaction fails.
+:::
diff --git a/articles/connections/passwordless/_sms-controller-objc.md b/articles/connections/passwordless/_old/_includes/_sms-controller-objc.md
similarity index 100%
rename from articles/connections/passwordless/_sms-controller-objc.md
rename to articles/connections/passwordless/_old/_includes/_sms-controller-objc.md
diff --git a/articles/connections/passwordless/_sms-controller-swift.md b/articles/connections/passwordless/_old/_includes/_sms-controller-swift.md
similarity index 100%
rename from articles/connections/passwordless/_sms-controller-swift.md
rename to articles/connections/passwordless/_old/_includes/_sms-controller-swift.md
diff --git a/articles/connections/passwordless/_sms-login-objc.md b/articles/connections/passwordless/_old/_includes/_sms-login-objc.md
similarity index 100%
rename from articles/connections/passwordless/_sms-login-objc.md
rename to articles/connections/passwordless/_old/_includes/_sms-login-objc.md
diff --git a/articles/connections/passwordless/_sms-login-swift.md b/articles/connections/passwordless/_old/_includes/_sms-login-swift.md
similarity index 100%
rename from articles/connections/passwordless/_sms-login-swift.md
rename to articles/connections/passwordless/_old/_includes/_sms-login-swift.md
diff --git a/articles/connections/passwordless/_sms-send-code-objc.md b/articles/connections/passwordless/_old/_includes/_sms-send-code-objc.md
similarity index 100%
rename from articles/connections/passwordless/_sms-send-code-objc.md
rename to articles/connections/passwordless/_old/_includes/_sms-send-code-objc.md
diff --git a/articles/connections/passwordless/_sms-send-code-swift.md b/articles/connections/passwordless/_old/_includes/_sms-send-code-swift.md
similarity index 100%
rename from articles/connections/passwordless/_sms-send-code-swift.md
rename to articles/connections/passwordless/_old/_includes/_sms-send-code-swift.md
diff --git a/articles/connections/passwordless/_touchid-configure-component-objc.md b/articles/connections/passwordless/_old/_includes/_touchid-configure-component-objc.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-configure-component-objc.md
rename to articles/connections/passwordless/_old/_includes/_touchid-configure-component-objc.md
diff --git a/articles/connections/passwordless/_touchid-configure-component-swift.md b/articles/connections/passwordless/_old/_includes/_touchid-configure-component-swift.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-configure-component-swift.md
rename to articles/connections/passwordless/_old/_includes/_touchid-configure-component-swift.md
diff --git a/articles/connections/passwordless/_touchid-controller-objc.md b/articles/connections/passwordless/_old/_includes/_touchid-controller-objc.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-controller-objc.md
rename to articles/connections/passwordless/_old/_includes/_touchid-controller-objc.md
diff --git a/articles/connections/passwordless/_touchid-controller-swift.md b/articles/connections/passwordless/_old/_includes/_touchid-controller-swift.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-controller-swift.md
rename to articles/connections/passwordless/_old/_includes/_touchid-controller-swift.md
diff --git a/articles/connections/passwordless/_touchid-init-client-objc.md b/articles/connections/passwordless/_old/_includes/_touchid-init-client-objc.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-init-client-objc.md
rename to articles/connections/passwordless/_old/_includes/_touchid-init-client-objc.md
diff --git a/articles/connections/passwordless/_touchid-init-client-swift.md b/articles/connections/passwordless/_old/_includes/_touchid-init-client-swift.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-init-client-swift.md
rename to articles/connections/passwordless/_old/_includes/_touchid-init-client-swift.md
diff --git a/articles/connections/passwordless/_touchid-login-method-objc.md b/articles/connections/passwordless/_old/_includes/_touchid-login-method-objc.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-login-method-objc.md
rename to articles/connections/passwordless/_old/_includes/_touchid-login-method-objc.md
diff --git a/articles/connections/passwordless/_touchid-login-method-swift.md b/articles/connections/passwordless/_old/_includes/_touchid-login-method-swift.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-login-method-swift.md
rename to articles/connections/passwordless/_old/_includes/_touchid-login-method-swift.md
diff --git a/articles/connections/passwordless/_touchid-properties-objc.md b/articles/connections/passwordless/_old/_includes/_touchid-properties-objc.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-properties-objc.md
rename to articles/connections/passwordless/_old/_includes/_touchid-properties-objc.md
diff --git a/articles/connections/passwordless/_touchid-properties-swift.md b/articles/connections/passwordless/_old/_includes/_touchid-properties-swift.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-properties-swift.md
rename to articles/connections/passwordless/_old/_includes/_touchid-properties-swift.md
diff --git a/articles/connections/passwordless/_touchid-signup-objc.md b/articles/connections/passwordless/_old/_includes/_touchid-signup-objc.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-signup-objc.md
rename to articles/connections/passwordless/_old/_includes/_touchid-signup-objc.md
diff --git a/articles/connections/passwordless/_touchid-signup-swift.md b/articles/connections/passwordless/_old/_includes/_touchid-signup-swift.md
similarity index 100%
rename from articles/connections/passwordless/_touchid-signup-swift.md
rename to articles/connections/passwordless/_old/_includes/_touchid-signup-swift.md
diff --git a/articles/connections/passwordless/_old/_includes/_using-lock-email.md b/articles/connections/passwordless/_old/_includes/_using-lock-email.md
new file mode 100644
index 0000000000..a0626fff45
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_using-lock-email.md
@@ -0,0 +1,9 @@
+When this code runs, it will ask the user for their email address:
+
+
+
+Then Auth0 will send to the user an email containing the one-time code:
+
+
+
+Lastly, the user enters the one-time password into Lock. Then, if the password is correct, the user is authenticated.
diff --git a/articles/connections/passwordless/_old/_includes/_using-lock-ios-email.md b/articles/connections/passwordless/_old/_includes/_using-lock-ios-email.md
new file mode 100644
index 0000000000..9d12403061
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_using-lock-ios-email.md
@@ -0,0 +1,53 @@
+<%= include('./_introduction-email', { isMobile: true }) %>
+
+## Setup
+
+<%= include('./_setup-email') %>
+
+## Implementation
+
+### Using Auth0 Lock
+
+<%= include('./_introduction-lock', { repository: 'Lock.iOS-OSX', platform: 'iOS', docsUrl: 'lock-ios' }) %>
+
+
+
+<%= include('./_using-lock-email', { platform: 'ios' }) %>
+
+This code will call `onAuthenticationBlock`, where the ID Token, Refresh Token, and user profile are typically stored. Then the user will be allowed to continue to the authenticated part of the application.
+
+
+
+### Using your own UI
+
+If you choose to build your own UI, your code will need to ask the user for their email address first. Then call the following method:
+
+
+
+## Authenticate users with a Magic Link via email
+
+<%= include('./_introduction-email-magic-link') %>
+
+Lastly, once the user is authenticated, your app will be able to access the user profile and tokens returned by Auth0.
diff --git a/articles/connections/passwordless/_old/_includes/_using-lock-ios-sms.md b/articles/connections/passwordless/_old/_includes/_using-lock-ios-sms.md
new file mode 100644
index 0000000000..5d7a6db223
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_using-lock-ios-sms.md
@@ -0,0 +1,49 @@
+<%= include('./_introduction-sms', { isMobile: true }) %>
+
+## Setup
+
+<%= include('./_setup-sms-twilio') %>
+
+## Implementation
+
+### Using Auth0 Lock
+
+<%= include('./_introduction-lock', { repository: 'Lock.iOS-OSX', platform: 'iOS', docsUrl: 'lock-ios' }) %>
+
+
+
+<%= include('./_using-lock-sms', { platform: 'ios' }) %>
+
+This code will call `onAuthenticationBlock`, where the ID Token, Refresh Token, and user profile are typically stored. Then the user will be allowed to continue to the authenticated part of the application.
+
+
+
+### Using your own UI
+
+If you choose to build your own UI, your code will need to ask the user for their phone number first. Then call the following method:
+
+
+
+Lastly, once the user is authenticated, your app will be able to access the user profile and tokens returned by Auth0.
diff --git a/articles/connections/passwordless/_old/_includes/_using-lock-ios-touchid.md b/articles/connections/passwordless/_old/_includes/_using-lock-ios-touchid.md
new file mode 100644
index 0000000000..01ecc54d1c
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_using-lock-ios-touchid.md
@@ -0,0 +1,100 @@
+A feature specific to iOS is the support for *Touch ID*, which allows users to authenticate with their fingerprint (biometric authentication).
+
+
+
+During sign-up, the library will generate a key pair on the device, create a user in Auth0, and register the public key for the user:
+
+
+
+The private key is stored in the keystore of the device. Each time a user initiates authentication with a valid fingerprint, *Touch ID* retrieves the private key from the keystore, creates a token, signs it with the private key and sends it to Auth0. Auth0 then returns an ID Token, the user profile and, optionally, a Refresh Token.
+
+::: note
+You can use Touch ID with an iPhone 5s or later, an iPad Air 2, or an iPad mini 3 or later.
+:::
+
+## Implementation
+
+### Using the Auth0 Lock
+
+<%= include('./_introduction-lock', { repository: 'Lock.iOS-OSX', platform: 'iOS', docsUrl: 'lock-ios' }) %>
+
+
+
+### Using your own UI
+
+If you choose to build your own UI, you must install our [TouchIDAuth](https://github.com/auth0/TouchIDAuth) library to handle the features specific to *Touch ID*.
+
+Begin by signing up a user in a Database Connection:
+
+
+
+::: note
+You can generate a random password to avoid asking the user for one at this time. The user can change it later.
+:::
+
+Once the user has signed up, use the `idToken` to register the public key for the user.
+
+First, you will need a place to store an Auth0 API application with the token until you register the key, and a place to store the TouchID component:
+
+
+
+Then, to begin authentication, add this line:
+
+<% if (language === "objc") { %>
+```objc
+[self.authentication start];
+```
+
+<% } else { %>
+```swift
+self.authentication.start()
+```
+<% } %>
diff --git a/articles/connections/passwordless/_old/_includes/_using-lock-sms.md b/articles/connections/passwordless/_old/_includes/_using-lock-sms.md
new file mode 100644
index 0000000000..74a8f80ca2
--- /dev/null
+++ b/articles/connections/passwordless/_old/_includes/_using-lock-sms.md
@@ -0,0 +1,9 @@
+When this code runs, it will ask the user for their phone number:
+
+
+
+Then Auth0 will use Twilio to send to the user an SMS containing the one-time code:
+
+
+
+Lastly, the user enters the one-time password into Lock. Then, if the password is correct, the user is authenticated.
diff --git a/articles/connections/passwordless/_version_warning_auth0js.md b/articles/connections/passwordless/_old/_includes/_version_warning_auth0js.md
similarity index 100%
rename from articles/connections/passwordless/_version_warning_auth0js.md
rename to articles/connections/passwordless/_old/_includes/_version_warning_auth0js.md
diff --git a/articles/connections/passwordless/_old/email.md b/articles/connections/passwordless/_old/email.md
new file mode 100644
index 0000000000..d287606cb7
--- /dev/null
+++ b/articles/connections/passwordless/_old/email.md
@@ -0,0 +1,36 @@
+---
+title: Implement Passwordless Email Authentication
+description: Learn how to authenticate users with either a one-time-code or a magic link sent by SMS.
+alias:
+ - email
+seo_alias: email
+topics:
+ - connections
+ - passwordless
+ - email
+contentType: how-to
+useCase: customize-connections
+---
+
+# Implement Passwordless Email Authentication
+
+<%= include('./_includes/_introduction-email', { isMobile: false }) %>
+
+## Setup
+
+<%= include('./_includes/_setup-email') %>
+
+## Single-Page Application Tutorials
+
+ - [Authenticate users with a one-time code via email](/connections/passwordless/spa-email-code)
+ - [Authenticate users with a magic link via email](/connections/passwordless/spa-email-link)
+
+## Regular Web Application Tutorials
+
+ - [Authenticate users with a one-time code via email](/connections/passwordless/regular-web-app-email-code)
+ - [Authenticate users with a magic link via email](/connections/passwordless/regular-web-app-email-link)
+
+## Mobile Tutorials
+
+ - [iOS](/connections/passwordless/ios-email-swift)
+ - [Android](/connections/passwordless/android-email)
diff --git a/articles/connections/passwordless/_old/faq.md b/articles/connections/passwordless/_old/faq.md
new file mode 100644
index 0000000000..c627a4fef4
--- /dev/null
+++ b/articles/connections/passwordless/_old/faq.md
@@ -0,0 +1,139 @@
+---
+title: Passwordless FAQ
+topics:
+ - connections
+ - passwordless
+contentType: reference
+useCase: customize-connections
+---
+# Passwordless FAQ
+
+## General Questions
+
+### Q: When is passwordless authentication the best option for login? How does this feature improve the user experience?
+
+**A:** The number of passwords that users must remember has become overwhelming, and passwords that aren’t used frequently are often forgotten. When a user forgets their password, they must recover it through email using a process more cumbersome than Auth0’s simple, passwordless user experience. For many users, recovering a lost password for infrequently visited sites and apps is a common and unpleasant experience.
+
+In a [recent survey](https://www.passwordboss.com/password-habits-survey-part-1/), 59% of users admit to reusing passwords because it is too difficult to remember them all. Although this habit avoids the password recovery scramble, it exposes these users to risk.
+
+Passwordless login is best for sites and apps where users maintain a presence but don’t visit often enough that they remember a unique password. This could encompass most of the Internet. For these sites, passwordless login creates a much better user experience and better security: no password resets or reuse, and no password database as a target for hackers.
+
+For frequently visited sites, passwordless authentication offers a streamlined and simple user experience. Many companies, such as Slack and [Medium](https://medium.com/the-story/signing-in-to-medium-by-email-aacc21134fcd), have embraced the passwordless login as more secure than passwords.
+
+### Q: When is passwordless login not a good idea? What are its limitations?
+
+**A:** For sites and apps that users access every day, the passwordless flow may feel slower than the muscle memory of quickly entering a memorized password. As with a username/password login, if an email account is hacked or a phone is stolen and unlocked, the passwordless login is compromised, but so is every site not using multi-factor authentication (MFA).
+
+Websites and web applications are trending toward longer session expirations so that users are not asked to login frequently, behaving more like native apps on a mobile device. Then, when a user initiates a sensitive operation, users are asked for *step-up* authentication such as a one-time password or a code from an authentication app like Google Authenticator. Auth0’s passwordless authentication takes the same approach. Like the `sudo` command on Linux, when the user initiates an activity that requires elevated privileges, they are presented with an extra challenge. Simple and effective, this procedure eliminates the hassle of multi-factor authentication, except when necessary.
+
+<%= include('./_includes/_single-browser-magic-link') %>
+
+### Q: Is it difficult for users to become accustomed to passwordless login?
+
+**A:** Passwordless login is so simple that most users will immediately get it. The user experience is nearly effortless, especially with *magic links* in emails. For most end-users, a passwordless login is easier than recalling a hard-to-remember password.
+
+### Q: How is passwordless login different from a social login?
+
+**A:** With a social login, the user is authenticated through a separate account that the user owns. Users need to remember and protect fewer passwords, and the site or app owner doesn’t need to manage any passwords.
+
+Social logins are appropriate when users are likely to have accounts on popular social providers, and when your application can gain additional features by interacting with the social provider’s API. Auth0 supports a wide range of social providers out-of-the-box with just a few lines of code. However, social logins can be confusing to some users because of the need to login to a different site, and of the grant page which asks for additional permissions to share their data. When users are confused or worried, they might abandon their sign-up. For these users, passwordless login has the advantage of not asking them to share anything except for their email, or phone number for SMS.
+
+One option is to offer users several popular social logins, and offer passwordless email as an alternative if they don’t have any social accounts or prefer not to use them.
+
+### Q: How much does passwordless authentication from Auth0 cost?
+
+**A:** There is no extra charge to use this feature. Passwordless authentication is included free with every Auth0 developer account, subscription, and custom plan.
+
+## How to use and configure Passwordless
+
+### Q: What are the advantages of using *magic links*?
+
+**A:** A *magic link* is a link sent to a user’s email that logs the user into your site or application with a single click. It provides the simplest user experience and makes the login process smooth and friction-free.
+
+### Q: What are the advantages of using emailed codes?
+
+**A:** An emailed code requires slightly more effort for end-users than a magic link. A numeric code is sent to the user’s email. The user then types this code into a response field of the Auth0 passwordless Lock widget on your site, which handles this part automatically. Once entered and validated, the user is logged in.
+
+### Q: What are the advantages of using codes delivered through SMS?
+
+**A:** Since users often have their phone nearby, SMS messages are likely to be delivered to the user’s hand or pocket.
+
+An SMS login, like an emailed code, requires slightly more effort for end-users than a *magic link*. Depending on the user’s mobile subscription plan, there may be a fee for them to receive SMS messages or these messages may count against a pool of available free messages. For such users, the added cost of using the SMS side-channel may not be considered worthwhile.
+
+### Q: Can I offer both email and SMS options at the same time?
+
+**A:** Using [Auth0’s Javascript SDK](https://github.com/auth0/auth0.js), you have complete control of how passwordless authentication works with your site or application. It’s easy to implement a mixed-mode user experience and build your own UI using the SDK. However, the passwordless Lock widget does not yet support this sort of mixed-mode interface. Such a mode may be added to future versions of the widget.
+
+### Q: How would a user sign-in to your application using a *magic link* from a device that doesn’t have access to the registered email account?
+
+**A:** A user may sign-up for your service using passwordless login with their personal email and may want to use that service at work but does not have their personal email account available from their work PC. If they visit the service on their work PC and ask to log in, providing their personal email address, the *magic link* is sent to their personal email account that they cannot access from their work PC.
+
+The simplest way to solve this problem would be for the user to forward the *magic link* email to their work email account, and click the link from their work PC. They could also create an account with their work email address and link the two accounts, logging in with either of them.
+
+If this is likely to be a common scenario for your end-users, you might want to consider using emailed codes, or codes sent through SMS, rather than emailed links.
+
+### Q: How do I style the passwordless Lock widget to my own brand identity?
+
+**A:** The passwordless Lock widget accepts two parameters to change its appearance: the *primaryColor* option to change background color and the *icon* option to add your brand’s icon. You can also style the widget by modifying the CSS stylesheet.
+
+If you need more design control, you can implement your own UI and call any of the passwordless connections through the [Auth0 JavaScript SDK](https://github.com/auth0/auth0.js).
+
+### Q: How do I select which high-volume messaging provider passwordless logins will use? What are my options?
+
+**A:** By default, your passwordless connections will be set-up to use Auth0’s messaging provider. However, this limits your ability to monitor and manage availability, troubleshoot issues, and connect to analytics. Accordingly, we recommend that you set up your own high-volume email or SMS provider.
+
+Auth0 supports **Twilio SMS** for passwordless login with codes sent via SMS, and **SendGrid**, **Mandrill**, and **Amazon SES** for email-based passwordless authentication. These providers are all supported in the Auth0 Dashboard. All you need are your API credentials.
+
+### Q: Can I configure a different messaging provider than the ones you support directly?
+
+**A:** Currently, it is supported only for codes sent via SMS. To learn more about how to configure your own SMS gateway to handle the delivery of those codes, see [Set Up Custom SMS Gateway for Passwordless Connections](/connections/passwordless/sms-gateway).
+
+### Q: How can I use Passwordless as another factor in multi-factor authentication?
+
+**A:** While Auth0’s passwordless connections (including SMS and email) are not built into the Auth0 Dashboard MFA capability at this time, Auth0’s flexible [rules execution pipeline](/rules) make it easy to use these passwordless authentication methods as part of an MFA flow. Rules are snippets of JavaScript that execute on the Auth0 server as part of the authentication pipeline and give you the flexibility to call APIs or perform arbitrary computations in order to implement customized authentication logic. Simply call the passwordless connection using a redirect rule, and treat it as a [custom MFA provider](/mfa).
+
+In future versions of passwordless connections, supported MFA providers will be built-in.
+
+### Q: What happens if a user changes email or phone number?
+
+**A:** A self-service method for changing email or phone number is not included in this version of passwordless authentication. An administrator can change this information using the Auth0 Dashboard.
+
+## Security
+
+### Q: What if someone gains access to a user’s email address?
+
+**A:** If someone gains access to a user’s email account, they will be able to log in with the user’s passwordless email login with either a link or a code. This is no different than for password-protected accounts, which use email as the back channel for password resets. Typically, you protect against this risk by enabling multi-factor authentication when your application detects activity that appears suspicious such as logging in from a new device, an unknown IP address, or outside the user’s country of residence.
+
+### Q: What if someone gains access to a user’s SMS messages?
+
+**A:** As with email, if a user’s SMS messages are compromised, someone can log in as the user with SMS codes. Many phones now have built-in protections against theft, such as fingerprint readers, complex unlock codes, and remote disable and wipe features. The best protection against this risk on your site or application is to use multi-factor authentication, requiring additional *step-up* authentication when the user tries to access sensitive data or perform sensitive actions.
+
+### Q: How does the system prevent an intercepted one-time code or link from being used to establish an unauthorized session?
+
+**A:** Think of an intercepted code or link as similar to a compromised email account or stolen phone. Once the link or code is in the wrong hands, it can be used to log in as that user. But codes and links have a short time-to-live (typically 5 minutes) and can only be used once. This limits the opportunity for a hacker to use an intercepted communication to a brief window. Security experts strongly recommend using encrypted end-to-end communication between email servers and applications to prevent the easy interception of email, and you might recommend this safeguard to your end users as part of your documentation. Implementation of multi-factor *step-up* authentication for sensitive data or actions will reduce this risk as well.
+
+### Q: How could I use Passwordless sign in with *step-up* multi-factor authentication to improve security for more sensitive data or actions?
+
+**A:** Auth0 features powerful [rules](/rules) - JavaScript snippets which run during the authentication process on the Auth0 server, and allow you to insert additional authentication elements when potentially high-risk logins are detected. For instance, if your application detects a user logging in from a previously unknown IP address with a location outside of the user’s home country, your application might request a password.
+
+In future versions of passwordless logins, support for multi-factor *step-up* authentication will be added as part of the passwordless configuration options, replacing the use of rules to implement this security enhancement.
+
+### Q: Since users can click a link to log in, how can I prevent a phishing attack in which the user receives a fraudulent email that appears legitimate, but contains a link to a site that tricks them into giving up their credentials?
+
+**A:** Phishing attacks are about stealing credentials (user-names and passwords) through trickery. If there are no passwords to steal, these attacks will become less common. Passwordless logins are a big step in reducing the prevalence of phishing.
+
+Since passwordless email logins with *magic links* include a link in the email that logs a user into your site, a hacker could use it to create a fraudulent imitation of your legitimate email to trick unsuspecting users into divulging their account credentials for some other site, like their email account.
+
+There are several effective ways to reduce this risk. One is through education. The email to your users might include a warning not to click the link unless they recently requested to log in, and a notice that they will never be asked for any password when logging into your site.
+
+Another way is to apply best practices for email authentication when using this feature. There are popular and effective standards for verifying email authenticity including **SPF**, **DKIM**, and **DMARC**. We strongly recommend utilizing these capabilities by [configuring your own email provider](/email) when you set up passwordless logins, including setting up [SPF and DKIM records](/email#spf-configuration). Your email provider may have more detailed information on email authentication and availability for you to explore.
+
+Since you are using Auth0 passwordless logins, there are no passwords to phish, and phishing attacks cannot compromise the credentials to your site or application. This is great news. Whenever email is a component of an authentication flow however, there is always the potential for phishing (if only for harvesting the credentials of other sites). Passwordless email authentication protects your brand and online reputation, while foiling scammers.
+
+### Q: How does the system protect against brute-force attacks (code guessing)?
+
+**A:** The 6-digit numeric codes are one-time use and expire in a short time (5 minutes by default). In addition, Auth0 includes rate-limiting and IP address blocking after several failed attempts. Accordingly, it is impractical to brute-force guess these codes. The application owner will be notified by email of any attempt and can unblock the IP address for a legitimate user.
+
+### Q: Our company uses an email security system that scans URLs and invalidates the token. What can we do?
+
+**A:** The only solution to this is to ask your users to whitelist the passwordless emails.
diff --git a/articles/connections/passwordless/_old/ios-magic-link.md b/articles/connections/passwordless/_old/ios-magic-link.md
new file mode 100644
index 0000000000..23b6c3bce6
--- /dev/null
+++ b/articles/connections/passwordless/_old/ios-magic-link.md
@@ -0,0 +1,94 @@
+---
+title: Lock iOS v1 Passwordless Magic Links
+description: Using Passwordless Magic Links with Lock for iOS v1
+public: false
+topics:
+ - connections
+ - passwordless
+ - email
+ - ios
+ - magic-links
+contentType: how-to
+useCase: customize-connections
+---
+
+# Lock iOS v1: Passwordless with Magic Link
+
+<%= include('../../_includes/_native_passwordless_warning') %>
+
+Using [Lock v1 for iOS](/libraries/lock-ios/v1), you can implement a Passwordless login flow using Magic Link authentication for your iOS applications.
+
+::: note
+Before beginning this tutorial, [enable Universal Links](/dashboard/guides/applications/enable-universal-links) between your iOS application and Auth0 Application.
+:::
+
+## Set Up Universal Link domains for your iOS app
+
+iOS needs to know which domains your application handles. To configure this:
+
+1. Go to your project's Xcode settings page and open the *Capabilities* tab.
+2. Find the *Associated Domains* section, and move the slider (located near the top right) so that it displays **On**. This enables the use of Associated Domains.
+3. Click on the **plus sign** to add your Auth0 Application's domain. You'll need to use the following format: `applinks:${account.namespace}`
+
+<%= include('./_includes/_custom-domains') %>
+
+
+
+## Pass callbacks to Lock
+
+::: note
+If you've already implemented Lock v1 for iOS, you have already configured callbacks to the Auth0 Lock Library.
+:::
+
+In the `AppDelegate` class of your iOS application, include the following code to pass callbacks to Auth0 Lock:
+
+```swift
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ var window: UIWindow?
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
+ A0Lock.sharedLock().applicationLaunchedWithOptions(launchOptions)
+ return true
+ }
+
+ func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
+ return A0Lock.sharedLock().handleURL(url, sourceApplication: app)
+ }
+
+ func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
+ return A0Lock.sharedLock().continueUserActivity(userActivity, restorationHandler: restorationHandler)
+ }
+}
+
+```
+
+### Enable Magic Link login strategy
+
+Because the Lock library handles the login flow, you'll indicate that it should use a Magic Link. To do this, you'll place the following code into the view controller that presents the Lock login screen:
+
+```swift
+let lock = A0Lock.sharedLock()
+let controller = lock.newEmailViewController()
+
+controller.useMagicLink = true // <--- ENABLE MAGIC LINKS!
+
+controller.onAuthenticationBlock = { (profile, token) in
+ // Do something with profile and token if necessary
+ self.dismissViewControllerAnimated(true, completion: { self.performSegueWithIdentifier("UserLoggedIn", sender: self) })
+}
+lock.presentEmailController(controller, fromController: self)
+```
+
+* The `newEmailViewController` creates an email login view controller.
+* Setting `userMagicLink` to `true` tells the email login view controller to use the Magic Link.
+
+### Test notes
+
+* Because Universal Links do not work on iOS simulators, you'll need an iOS-enabled device to test this implementation.
+* When testing, do not use the Gmail app to open the email that contains the Magic Link. Gmail opens links internally or using Chrome, both of which bypass the detection of the Universal Link by iOS.
+
+<%= include('./_includes/_single-browser-magic-link') %>
+
diff --git a/articles/connections/passwordless/_old/ios-sms-objc.md b/articles/connections/passwordless/_old/ios-sms-objc.md
new file mode 100644
index 0000000000..0033da04fd
--- /dev/null
+++ b/articles/connections/passwordless/_old/ios-sms-objc.md
@@ -0,0 +1,23 @@
+---
+title: Using Passwordless Authentication on iOS with SMS
+languages:
+ - name: Swift
+ url: swift
+ - name: Objective-C
+ url: objc
+topics:
+ - connections
+ - passwordless
+ - sms
+ - ios
+ - objective-c
+contentType: how-to
+useCase: customize-connections
+---
+# Using Passwordless on iOS with SMS
+
+
+
+<%= include('../../_includes/_native_passwordless_warning') %>
+
+<%= include('./_includes/_using-lock-ios-sms', { language: 'objc' }) %>
diff --git a/articles/connections/passwordless/_old/ios-sms-swift.md b/articles/connections/passwordless/_old/ios-sms-swift.md
new file mode 100644
index 0000000000..b440775ca9
--- /dev/null
+++ b/articles/connections/passwordless/_old/ios-sms-swift.md
@@ -0,0 +1,23 @@
+---
+title: Using Passwordless Authentication on iOS with SMS in Swift
+languages:
+ - name: Swift
+ url: swift
+ - name: Objective-C
+ url: objc
+topics:
+ - connections
+ - passwordless
+ - sms
+ - ios
+ - swift
+contentType: how-to
+useCase: customize-connections
+---
+# Using Passwordless on iOS with SMS
+
+
+
+<%= include('../../_includes/_native_passwordless_warning') %>
+
+<%= include('./_includes/_using-lock-ios-sms', { language: 'swift' }) %>
diff --git a/articles/connections/passwordless/_old/regular-web-app-email-code.md b/articles/connections/passwordless/_old/regular-web-app-email-code.md
new file mode 100644
index 0000000000..a2b895b470
--- /dev/null
+++ b/articles/connections/passwordless/_old/regular-web-app-email-code.md
@@ -0,0 +1,121 @@
+---
+title: Implement Passwordless Email in Regular Web Apps
+description: Learn how to authenticate users with a one-time code sent by email in a regular web apps.
+toc: true
+topics:
+ - connections
+ - web-apps
+ - passwordless
+ - email
+contentType: how-to
+useCase: customize-connections
+---
+# Implement Passwordless Email in Regular Web Apps
+
+<%= include('./_includes/_call-from-client-side') %>
+
+<%= include('./_includes/_introduction-email', { isMobile: false }) %>
+
+## Setup
+
+<%= include('./_includes/_setup-email') %>
+
+<%= include('./_includes/_setup-callback', {spa:false} )%>
+
+## Implementation
+
+### Use Lock (the Auth0 UI widget)
+
+<%= include('./_includes/_init-passwordless-lock') %>
+
+Then you can trigger the login using the `callbackURL` option to specify the endpoint that will handle the server-side authentication:
+
+```html
+
+
+
+Login
+```
+
+<%= include('./_includes/_custom-domains') %>
+
+This will open a dialog that asks the user for their email address:
+
+
+
+Then Auth0 will send an email to the user containing the one-time code:
+
+
+
+Lock will ask for the code that has been emailed to the provided address. The code can then be used as a one-time password to log in:
+
+
+
+Once the user enters the code received by email, Lock will authenticate the user and redirect to the specified `callbackURL`.
+
+::: note
+You can follow any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the server-side authentication callback.
+:::
+
+### Use your own UI
+
+You can perform passwordless authentication in your regular web app with your own custom UI using the [Auth0 JavaScript application library](/libraries/auth0js).
+
+<%= include('./_includes/_init-auth0js_v9', {redirectUri:true} ) %>
+
+You must provide a way for the user to enter a address to which the email will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
+
+```js
+function sendEmail(){
+ var email = $('input.email').val();
+
+ webAuth.passwordlessStart({
+ connection: 'email',
+ send: 'code',
+ email: email
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ // Hide the input and show the code entry screen
+ $('.enter-email').hide();
+ $('.enter-code').show();
+ });
+}
+```
+
+This will send an email to the provided address. The user must now enter the code they received into your custom UI. Then you can continue with the login as follows (assuming the name of your form inputs as `input.email` and `input.code`):
+
+```js
+function login(){
+ var email = $('input.email').val();
+ var code = $('input.code').val();
+
+ webAuth.passwordlessLogin({
+ connection: 'email',
+ email: email,
+ verificationCode: code
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ });
+};
+```
+
+If authentication is successful, the user will be redirected to the `redirectUri` specified in the Auth0 constructor.
+
+Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/_old/regular-web-app-email-link.md b/articles/connections/passwordless/_old/regular-web-app-email-link.md
new file mode 100644
index 0000000000..05014f9095
--- /dev/null
+++ b/articles/connections/passwordless/_old/regular-web-app-email-link.md
@@ -0,0 +1,95 @@
+---
+title: Implement Passwordless Email with Magic Links in Regular Web Apps
+description: Learn how to authenticate users with a magic link sent by email in a regular web application.
+toc: true
+topics:
+ - connections
+ - web-apps
+ - passwordless
+ - email
+contentType: how-to
+useCase: customize-connections
+---
+# Implement Passwordless Email with Magic Links in Regular Web Apps
+
+<%= include('./_includes/_call-from-client-side') %>
+
+<%= include('./_includes/_introduction-email-magic-link') %>
+
+## Setup
+
+<%= include('./_includes/_setup-email') %>
+
+<%= include('./_includes/_setup-callback', {spa:false} ) %>
+
+## Implementation
+
+### Use Lock (the Auth0 UI widget)
+
+<%= include('./_includes/_init-passwordless-lock') %>
+
+Then you can trigger the login using the `callbackURL` option to specify the endpoint that will handle the authentication on the server-side:
+
+```html
+
+
+Login
+```
+
+<%= include('./_includes/_custom-domains') %>
+
+This will open a dialog that asks the user for their email address.
+
+
+
+Then Auth0 will send an email to the user containing the magic link. After clicking the link, the user will be signed in to your application automatically and redirected to the specified `callbackURL`.
+
+<%= include('./_includes/_single-browser-magic-link') %>
+
+
+::: note
+You can follow any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the authentication callback server side.
+:::
+
+### Use your own UI
+
+You can perform passwordless authentication in your regular web app with your own custom UI using the [Auth0 JavaScript application library](/libraries/auth0js).
+
+<%= include('./_includes/_init-auth0js_v9', {redirectUri:true} ) %>
+
+You must provide a way for the user to enter an email to which the magic link will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
+
+```js
+function sendEmail(){
+ var email = $('input.email').val();
+
+ webAuth.passwordlessStart({
+ connection: 'email',
+ send: 'link',
+ email: email
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ // Hide the input and show a "Check your email for your login link!" screen
+ $('.enter-email').hide();
+ $('.check-email').show();
+ });
+}
+```
+
+This will send an email containing the magic link. After clicking the link, the user will be automatically signed in and redirected to the `redirectUri` which can be specified in the Auth0 constructor.
+
+Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/_old/regular-web-app-sms.md b/articles/connections/passwordless/_old/regular-web-app-sms.md
new file mode 100644
index 0000000000..20165ed166
--- /dev/null
+++ b/articles/connections/passwordless/_old/regular-web-app-sms.md
@@ -0,0 +1,122 @@
+---
+title: Implement Passwordless SMS in Regular Web Apps
+description: Learn how to authenticate users with a one-time code sent by SMS in a regular web application.
+toc: true
+topics:
+ - connections
+ - web-apps
+ - passwordless
+ - sms
+contentType: how-to
+useCase: customize-connections
+---
+# Implement Passwordless SMS in Regular Web Apps
+
+<%= include('./_includes/_call-from-client-side') %>
+
+<%= include('./_includes/_introduction-sms', { isMobile: false }) %>
+
+## Setup
+
+<%= include('./_includes/_setup-sms-twilio') %>
+
+<%= include('./_includes/_setup-callback', {spa:false} ) %>
+
+## Implementation
+
+### Use Lock
+
+<%= include('./_includes/_init-passwordless-lock') %>
+
+Then you can trigger the login widget with the following code:
+
+```html
+
+
+Login
+```
+
+<%= include('./_includes/_custom-domains') %>
+
+This will open a dialog that asks the user for their phone number.
+
+
+
+Then Auth0 will use Twilio to send an SMS to the user containing the one-time code:
+
+
+
+Lock will ask for the code that has been sent to the provided number via SMS. The code can then be used as a one-time password to log in:
+
+
+
+Once the user enters the code received via SMS, Lock will authenticate the user and redirect to the specified `callbackURL`.
+
+::: note
+You can follow any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the server-side authentication callback.
+:::
+
+### Use your own UI
+
+You can perform passwordless authentication in your regular web app with your own custom UI using the [Auth0 JavaScript application library](/libraries/auth0js).
+
+<%= include('./_includes/_init-auth0js_v9', {redirectUri:true} ) %>
+
+You must provide a way for the user to enter a phone number to which the SMS will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.phone-number`):
+
+```js
+function sendSMS(){
+ var phone = $('input.phone-number').val();
+
+ webAuth.passwordlessStart({
+ connection: 'sms',
+ send: 'code',
+ phoneNumber: phone
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ // Hide the input and show the code entry screen
+ $('.enter-phone').hide();
+ $('.enter-code').show();
+ });
+}
+```
+
+This will send an SMS to the provided phone number. The user must now enter the code they received into your custom UI. Then you can continue with the login as follows (assuming the name of your form inputs as `input.phone-number` and `input.code`):
+
+```js
+function login(){
+ var phone = $('input.phone-number').val();
+ var code = $('input.code').val();
+
+ webAuth.passwordlessLogin({
+ connection: 'sms',
+ phoneNumber: phone,
+ verificationCode: code
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ });
+};
+```
+
+If authentication is successful, the user will be redirected to the `redirectUri` specified in the Auth0 constructor.
+
+::: note
+You can follow up with any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the authentication callback on the server-side.
+:::
+
+Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/_old/regular-web-app.md b/articles/connections/passwordless/_old/regular-web-app.md
new file mode 100644
index 0000000000..6a2eaf2ed5
--- /dev/null
+++ b/articles/connections/passwordless/_old/regular-web-app.md
@@ -0,0 +1,21 @@
+---
+title: Implement Passwordless in Regular Web Apps
+description: Learn how to authenticate users without using a password in a regular web application.
+topics:
+ - connections
+ - web-apps
+ - passwordless
+contentType: how-to
+useCase: customize-connections
+---
+# Implement Passwordless in Regular Web Apps
+
+<%= include('./_includes/_call-from-client-side') %>
+
+<%= include('./_includes/_introduction', { withFingerprint: false }) %>
+
+## Tutorials for Regular Web Apps
+
+ - [Authenticate users with a one-time code via SMS](/connections/passwordless/regular-web-app-sms)
+ - [Authenticate users with a one-time code via email](/connections/passwordless/regular-web-app-email-code)
+ - [Authenticate users with a magic link via email](/connections/passwordless/regular-web-app-email-link)
diff --git a/articles/connections/passwordless/_old/spa-email-code.md b/articles/connections/passwordless/_old/spa-email-code.md
new file mode 100644
index 0000000000..782f061763
--- /dev/null
+++ b/articles/connections/passwordless/_old/spa-email-code.md
@@ -0,0 +1,148 @@
+---
+title: Implement Passwordless Email in Single-Page Apps
+description: Learn how to authenticate users with a one-time code sent by email in a Single-Page Application (SPA).
+topics:
+ - connections
+ - passwordless
+ - spa
+ - email
+contentType: how-to
+useCase: customize-connections
+---
+# Implement Passwordless Email in Single-Page Apps
+
+<%= include('./_includes/_introduction-email', { isMobile: false }) %>
+
+## Setup
+
+<%= include('./_includes/_setup-email') %>
+
+<%= include('./_includes/_setup-cors') %>
+
+## Implementation
+
+### Use Lock (the Auth0 UI widget)
+
+<%= include('./_includes/_init-passwordless-lock') %>
+
+Then you can trigger the login with the following code:
+
+```html
+
+
+Login
+```
+
+<%= include('./_includes/_custom-domains') %>
+
+First, this will open a dialog that asks the user for their email address:
+
+
+
+Then Auth0 will send an email to the user containing the one-time code:
+
+
+
+Lock will ask for the code that has been emailed to the provided address. The code can then be used as a one-time password to log in.
+
+
+
+Once the user enters the code received by email, Lock will authenticate them and call the callback function where the ID Token and profile will be available.
+
+### Use your own UI
+
+You can perform passwordless authentication in your SPA with your own custom UI using the [Auth0 JavaScript SDK](/libraries/auth0js).
+
+<%= include('./_includes/_init-auth0js_v9', {redirectUri:true} ) %>
+
+Be sure to provide a `redirectUri` and to set the `responseType: 'token'`.
+
+You must provide a way for the user to enter a address to which the email will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
+
+```js
+function sendEmail(){
+ var email = $('input.email').val();
+
+ webAuth.passwordlessStart({
+ connection: 'email',
+ send: 'code',
+ email: email
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ // Hide the input and show the code entry screen
+ $('.enter-email').hide();
+ $('.enter-code').show();
+ });
+}
+```
+
+This will send an email to the provided address. The user must now enter the code they received into your custom UI. Then you can continue with the login as follows (assuming the name of your form inputs as `input.email` and `input.code`):
+
+```js
+function login(){
+ var email = $('input.email').val();
+ var code = $('input.code').val();
+
+ webAuth.passwordlessLogin({
+ connection: 'email',
+ email: email,
+ verificationCode: code
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ // If successful, save the user's token and proceed
+ });
+};
+```
+
+The `passwordlessVerify` method will verify the Passwordless transaction, then redirect the user back to the `redirectUri` that was set. You will then need to parse the URL hash in order to acquire the token, and then call the `client.userInfo` method to acquire your user's information, as in the following example:
+
+```js
+$(document).ready(function() {
+ if(window.location.hash){
+ webAuth.parseHash({hash: window.location.hash}, function(err, authResult) {
+ if (err) {
+ return console.log(err);
+ } else if (authResult){
+ localStorage.setItem('accessToken', authResult.accessToken);
+ webAuth.client.userInfo(authResult.accessToken, function(err, user) {
+ if (err){
+ console.log('err',err);
+ alert('There was an error retrieving your profile: ' + err.message);
+ } else {
+ // Hide the login UI, show a user profile element with name and image
+ $('.login-box').hide();
+ $('.logged-in-box').show();
+ localStorage.setItem('user', user);
+ $('.nickname').text(user.nickname);
+ $('.avatar').attr('src', user.picture);
+ }
+ });
+ }
+ });
+ }
+});
+```
+
+Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/_old/spa-email-link.md b/articles/connections/passwordless/_old/spa-email-link.md
new file mode 100644
index 0000000000..80cb29cf2d
--- /dev/null
+++ b/articles/connections/passwordless/_old/spa-email-link.md
@@ -0,0 +1,110 @@
+---
+title: Implement Passwordless Email with Magic Links in Single-Page Apps
+description: Learn how to authenticate users with a magic link sent by email in a Single-Page Application (SPA).
+topics:
+ - connections
+ - passwordless
+ - email
+ - spa
+contentType: how-to
+useCase: customize-connections
+---
+# Implement Passwordless Email with Magic Links in Single-Page Apps
+
+<%= include('./_includes/_introduction-email-magic-link') %>
+
+## Setup
+
+<%= include('./_includes/_setup-email') %>
+
+<%= include('./_includes/_setup-callback', {spa:true} ) %>
+
+## Implementation
+
+### Use Lock (the Auth0 UI widget)
+
+<%= include('./_includes/_init-passwordless-lock') %>
+
+Then you can trigger the passwordless authentication using a magic link with the following code:
+
+```html
+
+
+
+
+Login
+```
+
+<%= include('./_includes/_custom-domains') %>
+
+The user will receive an email with the magic link. Once the user clicks on this link, Auth0 will handle the authentication and redirect back to the application.
+
+::: note
+You can follow any of the [Single-Page App Quickstarts](/quickstart/spa) to see more about using Auth0.js in a SPA.
+:::
+
+### Use your own UI
+
+You can perform passwordless authentication with a magic link in your single-page application using your own UI with the [Auth0 JavaScript client library](/libraries/auth0js).
+
+<%= include('./_includes/_init-auth0js_v9', {redirectUri:true} ) %>
+
+You must provide a way for the user to enter an email to which the magic link will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
+
+```js
+function sendEmail(){
+ var email = $('input.email').val();
+
+ webAuth.passwordlessStart({
+ connection: 'email',
+ send: 'link',
+ email: email
+ }, function (err,res) {
+ if (err) {
+ // Handle error
+ }
+ // Hide the input and show a "Check your email for your login link!" screen
+ $('.enter-email').hide();
+ $('.check-email').show();
+ });
+}
+```
+
+This will send an email containing the magic link. After clicking the link, the user will be automatically signed in and redirected to the `redirectUri` which can be specified in the Auth0 constructor, where you will need to parse the token with `webAuth.parseHash`:
+
+```js
+//parse hash on page load
+$(document).ready(function(){
+ webAuth.parseHash({hash: window.location.hash}, function(err, authResult) {
+ if (err) {
+ return console.log(err);
+ }
+
+ webAuth.client.userInfo(authResult.accessToken, function(err, user) {
+ // Now you have the user's information
+ });
+ });
+});
+```
+
+<%= include('./_includes/_single-browser-magic-link') %>
+
+
+Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/_old/user-guide.md b/articles/connections/passwordless/_old/user-guide.md
new file mode 100644
index 0000000000..e5889bda96
--- /dev/null
+++ b/articles/connections/passwordless/_old/user-guide.md
@@ -0,0 +1,58 @@
+---
+title: Passwordless Authentication User Guide
+topics:
+ - connections
+ - passwordless
+contentType:
+ - concept
+ - how-to
+ - reference
+useCase: customize-connections
+---
+# User Guide: Passwordless
+
+If you are using an app that allows for **Passwordless** authentication, you can register using either your **email address** or your **mobile phone number** instead of a login/password combination. Depending on which piece of information you provide, you will then access the app using a link that has been emailed to you or by providing a code that has been emailed or sent to you via SMS.
+
+* [Register and Authenticate Using Email](#register-and-authenticate-using-email)
+* [Register and Authenticate Using SMS](#register-and-authenticate-using-sms)
+* [Troubleshooting](#troubleshooting)
+
+## Register and Authenticate Using Email
+
+
+
+If you provide your **email address**, you will receive an email containing either:
+
+* a link you click on to authenticate yourself, or;
+* a code you provide to the app to authenticate yourself.
+
+### Authentication Using a Magic Link Received via Email
+
+You may opt to register and authenticate yourself using a magic link sent via email. Upon receipt, you will need to click on the link to access the app.
+
+
+
+<%= include('./_includes/_single-browser-magic-link') %>
+
+
+### Authentication Using a One-time Use Code Received via Email
+
+You may opt to register and authenticate yourself using a one-time use code that you receive via email.
+
+
+
+Once received, you can return to the app to enter the code and authenticate yourself.
+
+
+
+## Register and Authenticate Using SMS
+
+
+
+If you provide your **mobile phone number**, you will receive a code that you will provide to the app to validate yourself.
+
+
+
+The code can then be used as a one-time password to log in.
+
+
diff --git a/articles/connections/passwordless/_setup-callback.md b/articles/connections/passwordless/_setup-callback.md
deleted file mode 100644
index 4d0a6de9f9..0000000000
--- a/articles/connections/passwordless/_setup-callback.md
+++ /dev/null
@@ -1,3 +0,0 @@
-### Configure Callback URL
-
-For security purposes, you must add <% if(spa){ %>your page's URL<%} else {%>the callback URL<%}%> to the list of **Allowed callback URLs** in your application's [Settings section](${manage_url}/#/applications) of the Dashboard.
diff --git a/articles/connections/passwordless/_setup-cors.md b/articles/connections/passwordless/_setup-cors.md
deleted file mode 100644
index 78c533d24b..0000000000
--- a/articles/connections/passwordless/_setup-cors.md
+++ /dev/null
@@ -1,3 +0,0 @@
-### Configure CORS
-
-For security purposes, you must add your app's *origin URL* to the list of **Allowed Origins (CORS)** in your app's [Settings Section](${manage_url}/#/applications) of the Dashboard, unless this *origin URL* has been already added to the **Allowed callback URLs** list.
diff --git a/articles/connections/passwordless/_setup-email.md b/articles/connections/passwordless/_setup-email.md
deleted file mode 100644
index 42baed1483..0000000000
--- a/articles/connections/passwordless/_setup-email.md
+++ /dev/null
@@ -1,37 +0,0 @@
-### Optional: Configure an email provider
-
-By default, Auth0 sends the email from its own messaging provider. Optionally, you can [configure your own email provider](/email/providers) to better monitor and troubleshoot the email service.
-
-### Configure the connection
-
-In the Dashboard, on the **Email** page, under [Connections > Passwordless](${manage_url}/#/connections/passwordless), you can configure the contents and behavior of the email.
-
-
-
-#### Multi-Language Support
-
-The Message area supports usage of multiple languages.
-
-By making a call to the [/passwordless/start](/api/authentication/reference#get-code-or-link) authentication endpoint, you can set the value of an 'x-request-language' header to the language of your choice. If the value of this header is not set, the language will be extracted from the value in the 'accept-language' header that is automatically set by the browser.
-
-The Message area accepts Liquid syntax. You can use this syntax, combined with exposed parameter values, to programmatically construct elements of the message. For example, you can reference the `request_language` parameter to change the language of the message:
-
-```text
-{% if request_language contains 'dutch' %}
- Hier is uw verificatie code: {{ code }}
-{% endif %}
-
-{% if request_language contains 'fr-FR' %}
- Ceci est votre code: {{ code }}
-{% endif %}
-```
-
-The following parameters are available when defining the template:
-
-| Exposed Parameter | Description |
-|:------------------|:---------|
-| `code` | the password to use |
-| `link` | the magic link |
-| `application.name` | the name of the application name where the user is signing up |
-| `request_language` | the requested language for the message content |
-| `operation` | equals `change_email` when the template is triggered by an update to a user's email via the API, otherwise null |
diff --git a/articles/connections/passwordless/_setup-sms-twilio.md b/articles/connections/passwordless/_setup-sms-twilio.md
deleted file mode 100644
index 924f8c1208..0000000000
--- a/articles/connections/passwordless/_setup-sms-twilio.md
+++ /dev/null
@@ -1,62 +0,0 @@
-### Open an account with Twilio
-
-You will need a [Twilio Account SID](https://www.twilio.com/help/faq/twilio-basics/what-is-an-application-sid) and a [Twilio Auth Token](https://www.twilio.com/help/faq/twilio-basics/what-is-the-auth-token-and-how-can-i-change-it). These are the Twilio API credentials that Auth0 will use to send an SMS to the user.
-
-### Configure the connection
-
-In the Dashboard under [Connections > Passwordless](${manage_url}/#/connections/passwordless), set the SMS slider to the right to enable the SMS Passwordless feature.
-
-Enter your **Twilio Account SID** and **Twilio Auth Token** in the appropriate fields.
-
-::: note
-For information on obtaining a Twilio SID and Auth Token, see: [How to create an Application SID](https://www.twilio.com/help/faq/twilio-basics/what-is-an-application-sid) and [Auth Tokens and how to change them](https://www.twilio.com/help/faq/twilio-basics/what-is-the-auth-token-and-how-can-i-change-it).
-:::
-
-Select the **SMS Source** that users will see as the sender of the SMS.
-
-::: note
-For information on using Copilot, see: [Sending Messages with Copilot](https://www.twilio.com/docs/api/rest/sending-messages-copilot).
-:::
-
-Enter either your **Twilio Messaging Service SID** or a **From** phone number, depending on the **SMS Source** selected above.
-
-Lastly, enter the **Message** that will appear in the body of the SMS.
-
-::: note
-The `@@password@@` placeholder in the Message will be automatically replaced with the one-time password that is sent to the user.
-:::
-
-Click **SAVE**.
-
-
-
-#### Multi-Language Support
-
-The Message area supports usage of multiple languages.
-
-By making a call to the [/passwordless/start](/api/authentication/reference#get-code-or-link) authentication endpoint, you can set the value of an 'x-request-language' header to the language of your choice. If the value of this header is not set, the language will be extracted from the value in the 'accept-language' header that is automatically set by the browser.
-
-The Message area accepts Liquid syntax. You can use this syntax, combined with exposed parameter values, to programmatically construct elements of the message. For example, you can reference the `request_language` parameter to change the language of the message:
-
-```text
-{% if request_language contains 'dutch' %}
- Hier is uw verificatie code: {{ password }}
-{% endif %}
-
-{% if request_language contains 'fr-FR' %}
- Ceci est votre code: {{ password }}
-{% endif %}
-```
-
-The following paramaters are available when defining the template:
-
-| Exposed Parameter | Description |
-|:------------------|:---------|
-| `password` or `code` | the password to use |
-| `phone_number` | the user's phone number |
-| `application.name` | the name of the application name where the user is signing up |
-| `request_language` | the requested language for the message content |
-
-### Enable your apps
-
-Go to the **Apps** tab of the SMS settings and enable the apps for which you would like to use Passwordless SMS.
diff --git a/articles/connections/passwordless/_using-lock-email.md b/articles/connections/passwordless/_using-lock-email.md
deleted file mode 100644
index 8bd7d1a22f..0000000000
--- a/articles/connections/passwordless/_using-lock-email.md
+++ /dev/null
@@ -1,9 +0,0 @@
-When this code runs, it will ask the user for their email address:
-
-
-
-Then Auth0 will send to the user an email containing the one-time code:
-
-
-
-Lastly, the user enters the one-time password into Lock. Then, if the password is correct, the user is authenticated.
diff --git a/articles/connections/passwordless/_using-lock-ios-email.md b/articles/connections/passwordless/_using-lock-ios-email.md
deleted file mode 100644
index 30d25e34de..0000000000
--- a/articles/connections/passwordless/_using-lock-ios-email.md
+++ /dev/null
@@ -1,53 +0,0 @@
-<%= include('./_introduction-email', { isMobile: true }) %>
-
-## Setup
-
-<%= include('./_setup-email') %>
-
-## Implementation
-
-### Using Auth0 Lock
-
-<%= include('./_introduction-lock', { repository: 'Lock.iOS-OSX', platform: 'iOS', docsUrl: 'lock-ios' }) %>
-
-
-
-<%= include('./_using-lock-email', { platform: 'ios' }) %>
-
-This code will call `onAuthenticationBlock`, where the `id_token`, `refresh_token` and user profile are typically stored. Then the user will be allowed to continue to the authenticated part of the application.
-
-
-
-### Using your own UI
-
-If you choose to build your own UI, your code will need to ask the user for their email address first. Then call the following method:
-
-
-
-## Authenticate users with a Magic Link via e-mail
-
-<%= include('./_introduction-email-magic-link') %>
-
-Lastly, once the user is authenticated, your app will be able to access the user profile and tokens returned by Auth0.
diff --git a/articles/connections/passwordless/_using-lock-ios-sms.md b/articles/connections/passwordless/_using-lock-ios-sms.md
deleted file mode 100644
index 571d7c2035..0000000000
--- a/articles/connections/passwordless/_using-lock-ios-sms.md
+++ /dev/null
@@ -1,49 +0,0 @@
-<%= include('./_introduction-sms', { isMobile: true }) %>
-
-## Setup
-
-<%= include('./_setup-sms-twilio') %>
-
-## Implementation
-
-### Using Auth0 Lock
-
-<%= include('./_introduction-lock', { repository: 'Lock.iOS-OSX', platform: 'iOS', docsUrl: 'lock-ios' }) %>
-
-
-
-<%= include('./_using-lock-sms', { platform: 'ios' }) %>
-
-This code will call `onAuthenticationBlock`, where the `id_token`, `refresh_token` and user profile are typically stored. Then the user will be allowed to continue to the authenticated part of the application.
-
-
-
-### Using your own UI
-
-If you choose to build your own UI, your code will need to ask the user for their phone number first. Then call the following method:
-
-
-
-Lastly, once the user is authenticated, your app will be able to access the user profile and tokens returned by Auth0.
diff --git a/articles/connections/passwordless/_using-lock-ios-touchid.md b/articles/connections/passwordless/_using-lock-ios-touchid.md
deleted file mode 100644
index e495f329d5..0000000000
--- a/articles/connections/passwordless/_using-lock-ios-touchid.md
+++ /dev/null
@@ -1,100 +0,0 @@
-A feature specific to iOS is the support for *Touch ID*, which allows users to authenticate with their fingerprint (biometric authentication).
-
-
-
-During sign-up, the library will generate a key pair on the device, create a user in Auth0, and register the public key for the user:
-
-
-
-The private key is stored in the keystore of the device. Each time a user initiates authentication with a valid fingerprint, *Touch ID* retrieves the private key from the keystore, creates a token, signs it with the private key and sends it to Auth0. Auth0 then returns an `id_token`, the user profile and, optionally, a `refresh_token`.
-
-::: note
-You can use Touch ID with an iPhone 5s or later, an iPad Air 2, or an iPad mini 3 or later.
-:::
-
-## Implementation
-
-### Using the Auth0 Lock
-
-<%= include('./_introduction-lock', { repository: 'Lock.iOS-OSX', platform: 'iOS', docsUrl: 'lock-ios' }) %>
-
-
-
-### Using your own UI
-
-If you choose to build your own UI, you must install our [TouchIDAuth](https://github.com/auth0/TouchIDAuth) library to handle the features specific to *Touch ID*.
-
-Begin by signing up a user in a Database Connection:
-
-
-
-::: note
-You can generate a random password to avoid asking the user for one at this time. The user can change it later.
-:::
-
-Once the user has signed up, use the `idToken` to register the public key for the user.
-
-First, you will need a place to store an Auth0 API application with the token until you register the key, and a place to store the TouchID component:
-
-
-
-Then, to begin authentication, add this line:
-
-<% if (language === "objc") { %>
-```objc
-[self.authentication start];
-```
-
-<% } else { %>
-```swift
-self.authentication.start()
-```
-<% } %>
diff --git a/articles/connections/passwordless/_using-lock-sms.md b/articles/connections/passwordless/_using-lock-sms.md
deleted file mode 100644
index 95f45f04a1..0000000000
--- a/articles/connections/passwordless/_using-lock-sms.md
+++ /dev/null
@@ -1,9 +0,0 @@
-When this code runs, it will ask the user for their phone number:
-
-
-
-Then Auth0 will use Twilio to send to the user an SMS containing the one-time code:
-
-
-
-Lastly, the user enters the one-time password into Lock. Then, if the password is correct, the user is authenticated.
diff --git a/articles/connections/passwordless/android-email.md b/articles/connections/passwordless/android-email.md
deleted file mode 100644
index 51a99c2a60..0000000000
--- a/articles/connections/passwordless/android-email.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: Using Passwordless Authentication on Android with e-mail
----
-# Authenticate users with a one-time code via e-mail
-
-
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-<%= include('./_introduction-email', { isMobile: true }) %>
-
-## Setup
-
-<%= include('./_setup-email') %>
-
-## Implementation
-
-For detailed information on how to implement this, refer to [Lock Passwordless for Android documentation](/libraries/lock-android/passwordless).
diff --git a/articles/connections/passwordless/android-sms.md b/articles/connections/passwordless/android-sms.md
deleted file mode 100644
index 7b652ce740..0000000000
--- a/articles/connections/passwordless/android-sms.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: Using Passwordless Authentication on Android with SMS
----
-# Authenticate users with a one-time code via SMS
-
-
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-<%= include('./_introduction-sms', { isMobile: true }) %>
-
-## Setup
-
-<%= include('./_setup-sms-twilio') %>
-
-## Implementation
-
-For detailed information on how to implement this, refer to [Lock Passwordless for Android documentation](/libraries/lock-android/passwordless).
diff --git a/articles/connections/passwordless/android.md b/articles/connections/passwordless/android.md
deleted file mode 100644
index fcc443c3e1..0000000000
--- a/articles/connections/passwordless/android.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: Using Passwordless Authentication on Android
----
-# Passwordless Authentication on Android
-
-
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-<%= include('./_introduction', { withFingerprint: false }) %>
-
-## Tutorials for Android
-
- - [Authenticate users with a one-time code via SMS](/connections/passwordless/android-sms)
- - [Authenticate users with a one-time code via e-mail](/connections/passwordless/android-email)
diff --git a/articles/connections/passwordless/authentication-factors/email-magic-link.md b/articles/connections/passwordless/authentication-factors/email-magic-link.md
new file mode 100644
index 0000000000..718985d541
--- /dev/null
+++ b/articles/connections/passwordless/authentication-factors/email-magic-link.md
@@ -0,0 +1,18 @@
+---
+title: Passwordless Authentication with Magic Links
+description: Passwordless Authentication with Magic Links
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+---
+# Passwordless Authentication with Magic Links
+
+When implementing passwordless authentication with "magic links", the user is sent an email with a link in it. This link will allow them to login directly when clicking on it. It is similar in function to them getting an email with a one-time-use code in it, returning to your app, and entering the code, but without having to actually perform those steps.
+
+With magic link transactions, both the initial request and its response **must take place in the same browser or the transaction will fail**. This is particularly relevant for iOS users, who cannot change their default web browser. For example, the user might make the initial request using the Chrome browser, but when the user opens the magic link in their email, iOS automatically opens it in Safari (the default browser). If this happens, the transaction will fail.
+
+<%= include('../_includes/_introduction-email-magic-link') %>
+
+<%= include('../_includes/_setup-email') %>
diff --git a/articles/connections/passwordless/authentication-factors/email-otp.md b/articles/connections/passwordless/authentication-factors/email-otp.md
new file mode 100644
index 0000000000..22cbbd4f1b
--- /dev/null
+++ b/articles/connections/passwordless/authentication-factors/email-otp.md
@@ -0,0 +1,15 @@
+---
+title: Passwordless Authentication with Email
+description: Passwordless Authentication with Email
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+---
+# Passwordless Authentication with Email
+
+<%= include('../_includes/_introduction-email') %>
+
+<%= include('../_includes/_setup-email') %>
+
diff --git a/articles/connections/passwordless/authentication-factors/index.md b/articles/connections/passwordless/authentication-factors/index.md
new file mode 100644
index 0000000000..d7617ab2f7
--- /dev/null
+++ b/articles/connections/passwordless/authentication-factors/index.md
@@ -0,0 +1,18 @@
+---
+title: Passwordless Authentication Factors
+description: Describes the various authentication factors supported by Auth0 passwordless connections, including email, magic link, and SMS.
+topics:
+ - connections
+ - passwordless
+ - authentication
+useCase: customize-connections
+---
+# Passwordless Authentication Factors
+
+With Passwordless connections, users can log in without a password. Instead, they can use a variety of other authentication factors. Auth0 Passwordless connections support the following authentication factors:
+
+| Factor | Description |
+|-------------|-------------|
+| [Email](/connections/passwordless/email-otp) | The user is asked to enter their email address, to which Auth0 sends a one-time-use code. The user enters the code into your application. |
+| [Magic Link](/connections/passwordless/email-magic-link) | The user is asked to enter their email address, to which Auth0 sends an email with a link in it. The user clicks the link and is directly logged in to your application. |
+| [SMS](/connections/passwordless/sms-otp) | The user is asked to enter their phone number, to which Auth0 sends a one-time-use code. By default, Auth0 uses Twilio to send the code, but if you have a custom SMS gateway, you can modify your connection to use that instead. |
\ No newline at end of file
diff --git a/articles/connections/passwordless/authentication-factors/sms-otp.md b/articles/connections/passwordless/authentication-factors/sms-otp.md
new file mode 100644
index 0000000000..a602a64749
--- /dev/null
+++ b/articles/connections/passwordless/authentication-factors/sms-otp.md
@@ -0,0 +1,18 @@
+---
+title: Passwordless Authentication with SMS
+description: Learn about passwordless connections, Auth0-supported passwordless methods of authentication, and how to implement passwordless authentication with Auth0.
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+contentType:
+ - index
+ - concept
+useCase: customize-connections
+---
+# Passwordless Authentication with SMS
+
+<%= include('../_includes/_introduction-sms') %>
+
+<%= include('../_includes/_setup-sms-twilio') %>
diff --git a/articles/connections/passwordless/best-practices.md b/articles/connections/passwordless/best-practices.md
new file mode 100644
index 0000000000..7c7e6a7c16
--- /dev/null
+++ b/articles/connections/passwordless/best-practices.md
@@ -0,0 +1,62 @@
+---
+title: Passwordless Connections Best Practices
+description: Passwordless Connections Best Practices
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+ - concept
+---
+# Passwordless Connections Best Practices
+
+## Implementing login
+
+You can implement passwordless authentication by redirecting to Auth0's [Universal Login](/connections/passwordless/universal-login) or by [Embedding Login](/connections/passwordless/embedded-login) in your application.
+
+We always recommend that [you implement Universal Login](guides/login/universal-vs-embedded).
+
+## SMS and email as authentication factors
+
+Auth0's passwordless implementation enables authenticating users with a single factor. That single factor can be one-time-use code sent by email or sms, or a magic link sent by email.
+
+Even if using email or SMS can be more secure than a weak password, they have known issues:
+
+- Phone numbers are not sufficient for user authentication. The SS7 phone routing system used by cellular networks [has verified weaknesses](https://thehackernews.com/2017/05/ss7-vulnerability-bank-hacking.html) which have led to it not being recommended as an authentication factor. There are many attack vectors available, ranging from the use of social engineering, to swapping sim cards and buying access to the SS7 network.
+
+- Having an email address is not sufficient for user authentication (aliases, forwarding, multiple users in one account are all examples). Email providers vary in their security practices and some do not require any establishment of a user's identity. SMTP is a very old protocol, and many providers still route SMTP traffic unencrypted leading to an increased chance of an interception attack.
+
+We recommend that if you use passwordless authentication, you also implement [Multi-factor Authentication (MFA)](/mfa) with a different factor when the user performs a security-sensitive operation.
+
+## Preventing Phishing Attacks
+
+A possible phishing attack could look like:
+
+1. The user clicks a link in a malicious email or website.
+1. The user lands in the attacker's site, where they are prompted to enter their phone number to authenticate.
+1. The user enters the phone number, and the attacker enters the same phone number in the legitimate application.
+1. The legitimate application sends an SMS to the user.
+1. The user types the one-time-use code in the attacker's website.
+1. The attacker can now login to the legitimate website.
+
+To decrease the chances of success for this attack, the user should expect that the SMS clearly identifies the application. You should configure the SMS template so it mentions the tenant name and/or the Application Name:
+
+```text
+Your verification code for accessing's Acme @@application.name@@ is @@password@@
+```
+
+## Preventing brute force attacks
+
+Auth0 has the following protections against brute force attacks:
+
+* Only the most recent one-time-use code (or link) issued will be accepted. Once the latest one is issued, any others are invalidated. Once used, the latest one is also invalidated.
+* Only three failed attempts to input any single one-time-use code are allowed. After this, a new code will need to be requested.
+* The one-time-use code issued will be valid for three minutes (by default) before it expires.
+
+The one-time-use code expiration time can be altered at [Auth0 Dashboard > Authentication > Passwordless](${manage_url}/#/connections/passwordless).
+
+## Link accounts
+
+Users might want to authenticate using different passwordless factors during their lifetime. For example, they could initially sign up with an SMS, and later start authenticating with an email. You can achieve that by enabling them to link their different profiles using [account linking](/users/concepts/overview-user-account-linking).
+
+<%= include('./_includes/_rate_limit_server_side') %>
diff --git a/articles/connections/passwordless/email.md b/articles/connections/passwordless/email.md
deleted file mode 100644
index 5317d198d6..0000000000
--- a/articles/connections/passwordless/email.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: Email Passwordless Authentication
-connection: Email
-alias:
- - email
-seo_alias: email
----
-
-# Authenticate users with using Passwordless Authentication via Email
-
-<%= include('./_introduction-email', { isMobile: false }) %>
-
-## Setup
-
-<%= include('./_setup-email') %>
-
-## Single-page Application Tutorials
-
- - [Authenticate users with a one-time code via e-mail](/connections/passwordless/spa-email-code)
- - [Authenticate users with a magic link via e-mail](/connections/passwordless/spa-email-link)
-
-## Regular Web Application Tutorials
-
- - [Authenticate users with a one-time code via e-mail](/connections/passwordless/regular-web-app-email-code)
- - [Authenticate users with a magic link via e-mail](/connections/passwordless/regular-web-app-email-link)
-
-## Mobile Tutorials
-
- - [iOS](/connections/passwordless/ios-email-swift)
- - [Android](/connections/passwordless/android-email)
diff --git a/articles/connections/passwordless/embedded-login/index.md b/articles/connections/passwordless/embedded-login/index.md
new file mode 100644
index 0000000000..c75c8f4101
--- /dev/null
+++ b/articles/connections/passwordless/embedded-login/index.md
@@ -0,0 +1,28 @@
+---
+title: Passwordless Authentication with Embedded Login
+description: Passwordless Authentication with Embedded Login
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+---
+# Passwordless Authentication with Embedded Login
+
+Auth0 supports two way of implementing authentication: *Embedded Login* and *Universal Login*.
+
+The industry is aligned in that redirecting to the [Universal Login](/connections/passwordless/universal-login) page is the proper way to implement authentication in all apps, but in the case of Native Applications, sometimes customers prefer to implement Embedded Login for UX reasons.
+
+If you need to embed the login user interface in your application, you can do it by using our [Embedded Passwordless API](/connections/passwordless/relevant-api-endpoints) or our SDKs.
+
+Depending on the kind of application you want to build, you'll need to implement it differently:
+
+- For Single Page Applications (e.g. Angular / React), refer to [Embedded Passwordless Login in Single Page Applications](/connections/passwordless/embedded-login-spa).
+- For Native applications (iOS, Android, desktop applications) refer to [Embedded Passwordless Login in Native Applications](/connections/passwordless/embedded-login-native).
+- For Regular Web Applications (NodeJS, Java, Rails, .NET) please check [Embedded Passwordless Login in Regular Web Applications](/connections/passwordless/embedded-login-webapps).
+
+## Keep reading
+ * [Passwordless Authentication Overview](/connections/passwordless)
+ * [Best practices for Passwordless Authentication](connections/passwordless/best-practices)
+ * [Passwordless API Documentation](/connections/passwordless/relevant-api-endpoints)
+ * [Migrating from deprecated Passwordless endpoints](/migrations/guides/migration-oauthro-oauthtoken-pwdless)
diff --git a/articles/connections/passwordless/embedded-login/native.md b/articles/connections/passwordless/embedded-login/native.md
new file mode 100644
index 0000000000..6b97465a09
--- /dev/null
+++ b/articles/connections/passwordless/embedded-login/native.md
@@ -0,0 +1,116 @@
+---
+title: Embedded Passwordless Login in Native Applications
+description: Embedded Passwordless Login in Native Applications
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+---
+
+# Embedded Passwordless Login in Native Applications
+
+To use the Embedded Passwordless APIs in Native applications, make sure you enable the **Passwordless OTP** grant at [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications) in your application's settings under **Advanced Settings** > **Grant Types**.
+
+Passwordless authentication for Native applications consists of two steps:
+
+- Capture the user identifier in your application (the user's email or phone number) and invoke the `/passwordless/start` endpoint to initiate the passwordless flow. The user will get an email or an SMS with a one-time password.
+
+- Prompt the user for the one-time-use code, and call the `/oauth/token` endpoint to get authentication tokens.
+
+Below we list a few code snippets that can be used to call these API endpoints for different scenarios.
+
+**Send a one-time-use password via Email**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/passwordless/start",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"client_id\": \"${account.clientId}\", \"connection\": \"email\", \"email\": \"USER_EMAIL\", \"send\": \"code\"}"
+ }
+}
+```
+
+**Send a Magic via Email**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/passwordless/start",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"client_id\": \"${account.clientId}\", \"connection\": \"email\", \"email\": \"USER_EMAIL\", \"send\": \"link\"}"}
+}
+```
+
+**Send a one-time-use password via SMS**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/passwordless/start",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"client_id\": \"${account.clientId}\", \"connection\": \"sms\", \"phone_number\": \"USER_PHONE_NUMBER\", \"send\": \"code\"}"
+ }
+}
+```
+
+**Authenticate an SMS user**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"grant_type\": \"http://auth0.com/oauth/grant-type/passwordless/otp\", \"client_id\": \"${account.clientId}\", \"username\": \"USER_PHONE_NUMBER\", \"otp\": \"code\", \"realm\": \"sms\", \"audience\": \"your-api-audience\", \"scope\": \"openid profile email\"}"
+ }
+}
+```
+
+**Authenticate an Email user**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"grant_type\": \"http://auth0.com/oauth/grant-type/passwordless/otp\", \"client_id\": \"${account.clientId}\", \"username\": \"USER_EMAIL\", \"otp\": \"code\", \"realm\": \"email\", \"audience\": \"your-api-audience\", \"scope\": \"openid profile email\"}"
+ }
+}
+```
+
+If you prefer, you can use the Android or iOS SDKs, which wrap this APIs in a platform-friendly way:
+
+- [Lock Android Passwordless](/libraries/lock-android/passwordless)
+- [Lock iOS Passwordless](/libraries/lock-ios/passwordless)
+- [Auth0.Android Passwordless](/libraries/auth0-android/passwordless)
+- [Auth0.Swift Passwordless](/libraries/auth0-swift/passwordless)
+
+## Migrating from Legacy Implementations
+
+In the past, you could implement this scenario by using the `/oauth/ro` endpoint to exchange the one-time-use code for authentication tokens. Check the [migration guide](/migrations/guides/migration-oauthro-oauthtoken-pwdless) to learn how to update your code to use `/oauth/token`.
diff --git a/articles/connections/passwordless/embedded-login/relevant-api-endpoints.md b/articles/connections/passwordless/embedded-login/relevant-api-endpoints.md
new file mode 100644
index 0000000000..fe53db878c
--- /dev/null
+++ b/articles/connections/passwordless/embedded-login/relevant-api-endpoints.md
@@ -0,0 +1,112 @@
+---
+title: Using Passwordless APIs
+topics:
+ - connections
+ - passwordless
+ - api
+contentType: reference
+useCase: customize-connections
+---
+# Implementing Passwordless using APIs
+
+Passwordless APIs can be used in two scenarios:
+
+* When implementing Universal Login and you want to customize the login page using auth0.js to interact with Auth0.
+* When you want to embed the login flow in your application.
+
+If you decide to embed login, please make sure you understand the [security implications](/guides/login/universal-vs-embedded).
+
+You can learn more about how to implement Passwordless for Universal Login and Embedded login for different scenarios in these documents:
+
+- [Passwordless Authentication with Universal Login](/connections/passwordless/universal-login)
+- [Passwordless Authentication with Embedded Login](/connections/passwordless/embedded-login)
+
+
+## Passwordless endpoints
+
+### POST /passwordless/start
+
+The [POST /passwordless/start](/api/authentication#get-code-or-link) endpoint can be called to begin the Passwordless authentication process, for both Universal Login or Embedded Login.
+
+Depending on the parameters provided to the endpoint, Auth0 begins the user verification process by sending one of the following:
+
+* A single-use code via email or SMS message
+* A single-use link via email
+
+The API call needs to have the following structure:
+
+```json
+POST https://YOUR_DOMAIN/passwordless/start
+Content-Type: application/json
+{
+ "client_id": "YOUR_CLIENT_ID",
+ "client_secret": "YOUR_CLIENT_SECRET", // For Regular Web Applications
+ "connection": "email|sms",
+ "email": "EMAIL", //set for connection=email
+ "phone_number": "PHONE_NUMBER", //set for connection=sms
+ "send": "link|code", //if left null defaults to link
+ "authParams": { // any authentication parameters that you would like to add
+ "scope": "openid", // used when asking for a magic link
+ "state": "YOUR_STATE" // used when asking for a magic link, or from the custom login page
+ }
+}
+```
+
+If you use a magic link, Auth0 will redirect the user to the application after the link is clicked, and the user will be logged in.
+
+If you use a code, your application will need to prompt for that code, and then you should use the `/oauth/token` endpoint, or the `passwordlessLogin` method in the Auth0.js SDK to exchange that code for authentication tokens.
+
+### POST /oauth/token
+
+If you are implementing passwordless for Native Applications or Regular Web Applications, you need to use `/oauth/token` to exchange the OTP code for authentication tokens. You cannot use this endpoint from Single Page Applications.
+
+To achieve this you first need to enable the **Passwordless OTP** grant for your application at [Dashboard > Applications > Applications](${manage_url}/#/applications) in your application's settings under **Advanced Settings** > **Grant Types**.
+
+The user will receive the OTP code and your Native or Web application will prompt the user for it. When the user enters the code, you can complete the authentication flow by calling the `/oauth/token` endpoint with the following parameters:
+
+```json
+POST https://YOUR_AUTH0_DOMAIN/oauth/token
+Content-Type: application/json
+{
+ "grant_type" : "http://auth0.com/oauth/grant-type/passwordless/otp",
+ "client_id": "YOUR_CLIENT_ID",
+ "client_secret": "YOUR_CLIENT_SECRET", // only for web apps, native apps don’t have a client secret
+ "username":"", // or ""
+ "otp": "CODE",
+ "realm": "email", // or "sms"
+ "audience" : "your-api-audience", // in case you need an access token for a specific API
+ "scope": "openid profile email" // whatever scopes you need
+}
+```
+
+If all went well, Auth0 will return a response similar to the following:
+
+```json
+HTTP/1.1 200 OK
+Content-Type: application/json
+{
+"access_token":"eyJz93a...k4laUWw",
+"refresh_token":"GEbRxBN...edjnXbL",
+"id_token":"eyJ0XAi...4faeEoQ",
+"token_type":"Bearer",
+"expires_in":86400
+}
+```
+
+You can then decode the ID Token to get information about the user, or use the Access Token to call your API as normal.
+
+## Using Auth0.js
+
+When implementing Passwordless Authentication in Single Page Applications or in a customized Universal Login page, you should use Auth0.js and the included [`passwordlessLogin`](/libraries/auth0js/v9#verify-passwordless) method. The implementation is complex, so we recommend that you use the library instead of calling the APIs directly.
+
+## Rate Limiting in Passwordless Endpoints
+
+Auth0 rate limits and attack protection features only consider the IP from the machine that is making the API call. When the API call is made from a backend server, you usually want Auth0 to consider the IP from the end user, not the one from the server.
+
+Auth0 supports specifying an `auth0-forwarded-for` header in API calls, but it is only considered when:
+
+* The API call is made for a confidential application
+* The API call includes the client secret
+* The **Trust Token Endpoint IP Header** toggle is ON
+
+For a complete explanation, see this tutorial on [configuring your application to receive and trust the IP sent by your server](/api-auth/tutorials/using-resource-owner-password-from-server-side#configuring-the-auth0-application-to-receive-and-trust-the-ip-sent-by-your-server).
diff --git a/articles/connections/passwordless/embedded-login/spa.md b/articles/connections/passwordless/embedded-login/spa.md
new file mode 100644
index 0000000000..e46ecb8003
--- /dev/null
+++ b/articles/connections/passwordless/embedded-login/spa.md
@@ -0,0 +1,21 @@
+---
+title: Embedded Passwordless Authentication for SPAs
+description: Embedded Passwordless Authentication for SPAs
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+---
+# Embedded Passwordless Authentication for SPAs
+
+<%= include('../../../_includes/_embedded_login_warning') %>
+
+## Using Auth0's SDKs to implement Embedded Login
+
+You can implement Passwordless Login using Auth0's Lock widget or if you need complete control of the user experience, you can implement it using Auth0.js:
+
+- [Implementing passwordless with Lock.js](/libraries/lock/v11#passwordless)
+- [Implementing passwordless with Auth0.js](/libraries/auth0js#passwordless-login)
+
+<%= include('../_includes/_setup-cors') %>
diff --git a/articles/connections/passwordless/embedded-login/webapps.md b/articles/connections/passwordless/embedded-login/webapps.md
new file mode 100644
index 0000000000..65334f61ed
--- /dev/null
+++ b/articles/connections/passwordless/embedded-login/webapps.md
@@ -0,0 +1,116 @@
+---
+title: Embedded Passwordless Login in Regular Web Applications
+description: Embedded Passwordless Login in Regular Web Applications
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+---
+
+# Embedded Passwordless Login in Regular Web Applications
+
+To use the Embedded Passwordless APIs in Regular Web Applications, make sure you enable the **Passwordless OTP** grant at [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications) in your application's settings under **Advanced Settings** > **Grant Types**.
+
+Passwordless authentication for Regular Web Applications consists of two steps:
+
+- Capture the user identifier in your application (the user's email or phone number) and invoke the `/passwordless/start` endpoint to initiate the passwordless flow. The user will get an email, an SMS with a one-time-use code or a magic link.
+
+- If you did not send a magic link, you need to prompt the user for the one-time-use code, and call the `/oauth/token` endpoint to get authentication tokens.
+
+Note that when using magic links, you don't need to call `/oauth/token`. The user will click the magic link and it will be redirected to the application's callback URL.
+
+Below we list a few code snippets that can be used to call these API endpoints for different scenarios. Auth0 SDKs for backend technologies (Java, .NET, Ruby, PHP, Python, Node JS) haven't been updated yet to support these endpoints, so you will need to invoke them directly.
+
+**Send a one-time-use code via Email**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/passwordless/start",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"connection\": \"email\", \"email\": \"USER_EMAIL\",\"send\": \"code\"}"
+ }
+}
+```
+
+**Send a magic link via Email**
+
+You need to specify `send` = `link`.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/passwordless/start",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"connection\": \"email\", \"email\": \"USER_EMAIL\",\"send\": \"link\"}"
+ }
+}
+```
+
+**Send a one-time-use password via SMS**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/passwordless/start",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"connection\": \"sms\", \"phone_number\": \"USER_PHONE_NUMBER\",\"send\": \"code\"}"
+ }
+}
+```
+
+**Authenticate an SMS user**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"grant_type\": \"http://auth0.com/oauth/grant-type/passwordless/otp\", \"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"username\": \"USER_PHONE_NUMBER\", \"otp\": \"code\", \"realm\": \"sms\", \"audience\": \"your-api-audience\",\"scope\": \"openid profile email\"}"
+ }
+}
+```
+
+**Authenticate an Email user**
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [{
+ "name": "Content-Type",
+ "value": "application/json"
+ }],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"grant_type\": \"http://auth0.com/oauth/grant-type/passwordless/otp\", \"client_id\": \"${account.clientId}\", \"client_secret\": \"YOUR_CLIENT_SECRET\", \"username\": \"USER_EMAIL\", \"otp\": \"code\", \"realm\": \"email\", \"audience\": \"your-api-audience\", \"scope\": \"openid profile email\"}"}
+}
+```
+
+**Authenticate a user through a magic link**
+
+When you send a magic link, you don't need to call an API to authenticate the user. Users will click the link and get redirected to the callback URL.
+
+<%= include('../_includes/_rate_limit_server_side') %>
+
diff --git a/articles/connections/passwordless/faq.md b/articles/connections/passwordless/faq.md
deleted file mode 100644
index 6086c0929a..0000000000
--- a/articles/connections/passwordless/faq.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# Passwordless FAQ
-
-## General Questions
-
-### Q: When is passwordless authentication the best option for login? How does this feature improve the user experience?
-
-**A:** The number of passwords that users must remember has become overwhelming, and passwords that aren’t used frequently are often forgotten. When a user forgets their password, they must recover it through email using a process more cumbersome than Auth0’s simple, passwordless user experience. For many users, recovering a lost password for infrequently visited sites and apps is a common and unpleasant experience.
-
-In a [recent survey](https://www.passwordboss.com/password-habits-survey-part-1/), 59% of users admit to reusing passwords because it is too difficult to remember them all. Although this habit avoids the password recovery scramble, it exposes these users to risk.
-
-Passwordless login is best for sites and apps where users maintain a presence but don’t visit often enough that they remember a unique password. This could encompass most of the Internet. For these sites, passwordless login creates a much better user experience and better security: no password resets or reuse, and no password database as a target for hackers.
-
-For frequently visited sites, passwordless authentication offers a streamlined and simple user experience. Many companies, such as Slack and [Medium](https://medium.com/the-story/signing-in-to-medium-by-email-aacc21134fcd), have embraced the passwordless login as more secure than passwords.
-
-### Q: When is passwordless login not a good idea? What are its limitations?
-
-**A:** For sites and apps that users access every day, the passwordless flow may feel slower than the muscle memory of quickly entering a memorized password. As with a username/password login, if an email account is hacked or a phone is stolen and unlocked, the passwordless login is compromised, but so is every site not using multi-factor authentication.
-
-Websites and web applications are trending toward longer session expirations so that users are not asked to login frequently, behaving more like native apps on a mobile device. Then, when a user initiates a sensitive operation, users are asked for *step-up* authentication such as a one-time password or a code from an authentication app like Google Authenticator. Auth0’s passwordless authentication takes the same approach. Like the `sudo` command on Linux, when the user initiates an activity that requires elevated privileges, they are presented with an extra challenge. Simple and effective, this procedure eliminates the hassle of multi-factor authentication, except when necessary.
-
-### Q: Is it difficult for users to become accustomed to passwordless login?
-
-**A:** Passwordless login is so simple that most users will immediately get it. The user experience is nearly effortless, especially with *magic links* in emails or with Apple *Touch ID*. For most end-users, a passwordless login is easier than recalling a hard-to-remember password.
-
-### Q: How is passwordless login different from a social login?
-
-**A:** With a social login, the user is authenticated through a separate account that the user owns. Users need to remember and protect fewer passwords, and the site or app owner doesn’t need to manage any passwords.
-
-Social logins are appropriate when users are likely to have accounts on popular social providers, and when your application can gain additional features by interacting with the social provider’s API. Auth0 supports a wide range of social providers out-of-the-box with just a few lines of code. However, social logins can be confusing to some users because of the need to login to a different site, and of the grant page which asks for additional permissions to share their data. When users are confused or worried, they might abandon their sign-up. For these users, passwordless login has the advantage of not asking them to share anything except for their email, or phone number for SMS.
-
-One option is to offer users several popular social logins, and offer passwordless email as an alternative if they don’t have any social accounts or prefer not to use them.
-
-### Q: How much does passwordless authentication from Auth0 cost?
-
-**A:** There is no extra charge to use this feature. Passwordless authentication is included free with every Auth0 developer account, subscription, and custom plan.
-
-## How to use and configure Passwordless
-
-### Q: What are the advantages of using *magic links*?
-
-**A:** A *magic link* is a link sent to a user’s email that logs the user into your site or application with a single click. It provides the simplest user experience and makes the login process smooth and friction-free.
-
-### Q: What are the advantages of using emailed codes?
-
-**A:** An emailed code requires slightly more effort for end-users than a magic link. A numeric code is sent to the user’s email. The user then types this code into a response field of the Auth0 passwordless lock widget on your site, which handles this part automatically. Once entered and validated, the user is logged in.
-
-### Q: What are the advantages of using codes delivered through SMS?
-
-**A:** Since users often have their phone nearby, SMS messages are likely to be delivered to the user’s hand or pocket. Typically, it’s impossible to steal SMS service without being in possession of the phone or SIM that is hard-coded with the wireless number. This eliminates the potential for malicious access through stolen email credentials, making SMS logins more secure.
-
-An SMS login, like an emailed code, requires slightly more effort for end-users than a *magic link*. Depending on the user’s mobile subscription plan, there may be a fee for them to receive SMS messages or these messages may count against a pool of available free messages. For such users, the added cost of using the SMS side-channel may not be considered worthwhile.
-
-### Q: Can I offer both email and SMS options at the same time?
-
-**A:** Using [Auth0’s Javascript SDK](https://github.com/auth0/auth0.js), you have complete control of how passwordless authentication works with your site or application. It’s easy to implement a mixed-mode user experience and build your own UI using the SDK. However, the passwordless lock widget does not yet support this sort of mixed-mode interface. Such a mode may be added to future versions of the widget.
-
-### Q: How would a user sign-in to your application using a *magic link* from a device that doesn’t have access to the registered email account?
-
-**A:** A user may sign-up for your service using passwordless login with their personal email and may want to use that service at work but does not have their personal email account available from their work PC. If they visit the service on their work PC and ask to log in, providing their personal email address, the *magic link* is sent to their personal email account that they cannot access from their work PC.
-
-The simplest way to solve this problem would be for the user to forward the *magic link* email to their work email account, and click the link from their work PC. They could also create an account with their work email address and link the two accounts, logging in with either of them.
-
-If this is likely to be a common scenario for your end-users, you might want to consider using emailed codes, or codes sent through SMS, rather than emailed links.
-
-### Q: How do I style the passwordless lock widget to my own brand identity?
-
-**A:** The passwordless lock widget accepts two parameters to change its appearance: the *primaryColor* option to change background color and the *icon* option to add your brand’s icon. You can also style the widget by modifying the CSS stylesheet.
-
-If you need more design control, you can implement your own UI and call any of the passwordless connections through the [Auth0 JavaScript SDK](https://github.com/auth0/auth0.js).
-
-### Q: How do I select which high-volume messaging provider passwordless logins will use? What are my options?
-
-**A:** By default, your passwordless connections will be set-up to use Auth0’s messaging provider. However, this limits your ability to monitor and manage availability, troubleshoot issues, and connect to analytics. Accordingly, we recommend that you set up your own high-volume email or SMS provider.
-
-Auth0 supports **Twilio SMS** for passwordless login with codes sent via SMS, and **SendGrid**, **Mandrill**, and **Amazon SES** for email-based passwordless authentication. These providers are all supported in the Auth0 dashboard. All you need are your API credentials.
-
-### Q: Can I configure a different messaging provider than the ones you support directly?
-
-**A:** Currently it is supported only for codes sent via SMS, you can follow [this link](/connections/passwordless/sms-gateway) to read more on how to configure your own SMS gateway to handle the delivery of those codes.
-
-### Q: How can I use Passwordless as another factor in multi-factor authentication?
-
-**A:** While Auth0’s passwordless connections (including SMS, email, and Apple *Touch ID*) are not built into the dashboard MFA capability at this time, Auth0’s flexible [rules execution pipeline](/rules) make it easy to use these passwordless authentication methods as part of an MFA flow. Rules are snippets of JavaScript that execute on the Auth0 server as part of the authentication pipeline and give you the flexibility to call APIs or perform arbitrary computations in order to implement customized authentication logic. Simply call the passwordless connection using a redirect rule, and treat it as a [custom MFA provider](/mfa).
-
-In future versions of passwordless connections, supported MFA providers will be built-in.
-
-### Q: What are the advantages of Apple *Touch ID* for passwordless authentication?
-
-**A:** Apple’s *Touch ID* fingerprint identity system is an easy way for users to identify themselves to their iPhone or iPad equipped with a fingerprint scanner. To the user, the application unlocks with the touch of a finger.
-
-After a one-time enrollment process, each time the user logs into your app, the *Touch ID* passwordless library uses the matched fingerprint to retrieve a private key saved in the IOS key store. *Touch ID* then generates and signs a JWT with that private key and sends it to Auth0. Auth0 validates the JWT with the user’s saved public key, and returns a token authenticating the user.
-
-The disadvantage of *Touch ID* as a means of authenticating users is that it only works on native IOS apps installed on later-model iPhones and iPads. It does not work on other devices, like Android, nor can it protect a website or web application. Also, a backup password authentication mechanism must be available to handle new or lost devices. Auth0 makes it simple to link accounts so that you can offer *Touch ID* on Apple devices, and SMS or email-based passwordless logins for other mobile platforms and the web.
-
-Auth0’s standard Lock widget for IOS fully supports *Touch ID* with a very simple UI that is easily styled to your brand identity. You can implement passwordless login for your IOS app with just a few lines of code.
-
-### Q: Does the Passwordless Lock Widget support Apple *Touch ID*?
-
-**A:** No. For *Touch ID* passwordless logins, the standard Auth0 IOS lock widget provides all the same benefits. The web-based passwordless lock widget doesn’t support *Touch ID*.
-
-### Q: Can I combine email or SMS Passwordless authentication with Apple *Touch ID*?
-
-**A:** Instead of using a backup password to handle new or lost devices, you can use the email or SMS passwordless login and link the two user identities through Auth0’s account linking feature. Your application will recognize the same authenticated user whether they log in through *Touch ID*, or through email or SMS.
-
-### Q: What happens if a user changes email or phone number?
-
-**A:** A self-service method for changing email or phone number is not included in this version of passwordless authentication. An administrator can change this information using the Auth0 Dashboard.
-
-## Security
-
-### Q: What if someone gains access to a user’s email address?
-
-**A:** If someone gains access to a user’s email account, they will be able to log in with the user’s passwordless email login with either a link or a code. This is no different than for password-protected accounts, which use email as the back channel for password resets. Typically, you protect against this risk by enabling multi-factor authentication when your application detects activity that appears suspicious such as logging in from a new device, an unknown IP address, or outside the user’s country of residence.
-
-### Q: What if someone gains access to a user’s SMS messages?
-
-**A:** As with email, if a user’s SMS messages are compromised, someone can log in as the user with SMS codes. Many phones now have built-in protections against theft, such as fingerprint readers, complex unlock codes, and remote disable and wipe features. The best protection against this risk on your site or application is to use multi-factor authentication, requiring additional *step-up* authentication when the user tries to access sensitive data or perform sensitive actions.
-
-### Q: How does the system prevent an intercepted one-time code or link from being used to establish an unauthorized session?
-
-**A:** Think of an intercepted code or link as similar to a compromised email account or stolen phone. Once the link or code is in the wrong hands, it can be used to log in as that user. But codes and links have a short time-to-live (typically 5 minutes) and can only be used once. This limits the opportunity for a hacker to use an intercepted communication to a brief window. Security experts strongly recommend using encrypted end-to-end communication between email servers and applications to prevent the easy interception of email, and you might recommend this safeguard to your end users as part of your documentation. Implementation of multi-factor *step-up* authentication for sensitive data or actions will reduce this risk as well.
-
-### Q: How could I use Passwordless sign in with *step-up* multi-factor authentication to improve security for more sensitive data or actions?
-
-**A:** Auth0 features powerful [rules](/rules) - JavaScript snippets which run during the authentication process on the Auth0 server, and allow you to insert additional authentication elements when potentially high-risk logins are detected. For instance, if your application detects a user logging in from a previously unknown IP address with a location outside of the user’s home country, your application might request a password, or ask a security question from inside of Auth0’s authentication flow.
-
-In future versions of passwordless logins, support for multi-factor *step-up* authentication will be added as part of the passwordless configuration options, replacing the use of rules to implement this security enhancement.
-
-### Q: Since users can click a link to log in, how can I prevent a phishing attack in which the user receives a fraudulent email that appears legitimate, but contains a link to a site that tricks them into giving up their credentials?
-
-**A:** Phishing attacks are about stealing credentials (user-names and passwords) through trickery. If there are no passwords to steal, these attacks will become less common. Passwordless logins are a big step in reducing the prevalence of phishing.
-
-Since passwordless email logins with *magic links* include a link in the email that logs a user into your site, a hacker could use it to create a fraudulent imitation of your legitimate email to trick unsuspecting users into divulging their account credentials for some other site, like their email account.
-
-There are several effective ways to reduce this risk. One is through education. The email to your users might include a warning not to click the link unless they recently requested to log in, and a notice that they will never be asked for any password when logging into your site.
-
-Another way is to apply best practices for email authentication when using this feature. There are popular and effective standards for verifying email authenticity including **SPF**, **DKIM**, and **DMARC**. We strongly recommend utilizing these capabilities by [configuring your own email provider](/email) when you set up passwordless logins, including setting up [SPF and DKIM records](/email#spf-configuration). Your email provider may have more detailed information on email authentication and availability for you to explore.
-
-Since you are using Auth0 passwordless logins, there are no passwords to phish, and phishing attacks cannot compromise the credentials to your site or application. This is great news. Whenever email is a component of an authentication flow however, there is always the potential for phishing (if only for harvesting the credentials of other sites). Passwordless email authentication protects your brand and online reputation, while foiling scammers.
-
-### Q: How does the system protect against brute-force attacks (code guessing)?
-
-**A:** The 6-digit numeric codes are one-time use and expire in a short time (5 minutes by default). In addition, Auth0 includes rate-limiting and IP address blocking after several failed attempts. Accordingly, it is impractical to brute-force guess these codes. The application owner will be notified by email of any attempt and can unblock the IP address for a legitimate user.
-
-### Q: Our company uses an email security system that scans URLs and invalidates the token. What can we do?
-
-**A:** The only solution to this is to ask your users to whitelist the passwordless emails.
diff --git a/articles/connections/passwordless/index.md b/articles/connections/passwordless/index.md
index a44e3da2bf..31c7f5faff 100644
--- a/articles/connections/passwordless/index.md
+++ b/articles/connections/passwordless/index.md
@@ -1,52 +1,114 @@
---
-title: Using Passwordless SMS & Email Authentication with Auth0
+title: Passwordless Connections
+description: Learn about passwordless connections, Auth0-supported passwordless methods of authentication, and how to implement passwordless authentication with Auth0.
+toc: true
url: /connections/passwordless
+topics:
+ - connections
+ - passwordless
+ - authentication
+contentType:
+ - index
+ - concept
+useCase: customize-connections
---
-# Using Passwordless Authentication
+# Passwordless Connections
-
+Passwordless connections allow users to log in without the need to remember a password. Instead, users enter their mobile phone number or email address and receive a one-time code or link, which they can then use to log in.
-<%= include('./_introduction', { withFingerprint: false }) %>
+When a user authenticates via Passwordless, the user is attached to the connection using Auth0 as the Identity Provider (IdP). Since you can't force users to use the same mobile phone number or email address every time they authenticate, users may end up with multiple user profiles in the Auth0 datastore; you can link multiple user profiles through [account linking](/extensions/account-link).
-## Tutorials
+A passwordless connection is another type of connection separate from any existing database, social, or Enterprise connections. Even though a user from an Auth0 user database or social provider might share the same email address, the identity associated with their passwordless connection is distinct. As with linking multiple email addresses or mobile phone numbers used for the passwordless connection, [account linking](/extensions/account-link) can also be used to associate a passwordless identity with identities from other types of connections.
-See the following tutorials for a step-by-step guide on how to implement passwordless authentication for each of these scenarios:
+::: note
+You cannot create passwordless users from the Auth0 Dashboard. Create them directly from the [Management API](/api/management/v2#!/Users/post_users) if signup is disabled. In the **Connection** field, use **email** for passwordless users using an email address and **sms** for passwordless users using a mobile phone number.
+:::
-### Passwordless on Single Page Apps
+Passwordless differs from Multi-factor Authentication (MFA) in that only one factor is used to authenticate a user—the one-time code or link received by the user. If you want to require that users log in with a one-time code or link **in addition** to another factor (e.g., username/password or a social Identity Provider, such as Google), see [Multi-factor Authentication (MFA)](/mfa).
- - [Authenticate users with a one time code via SMS](/connections/passwordless/spa-sms)
- - [Authenticate users with a one time code via e-mail](/connections/passwordless/spa-email-code)
- - [Authenticate users with a magic link via e-mail](/connections/passwordless/spa-email-link)
+## Benefits
-### Passwordless on Regular Web Apps
+The benefits of using Passwordless authentication include:
- - [Authenticate users with a one time code via SMS](/connections/passwordless/regular-web-app-sms)
- - [Authenticate users with a one time code via e-mail](/connections/passwordless/regular-web-app-email-code)
- - [Authenticate users with a magic link via e-mail](/connections/passwordless/regular-web-app-email-link)
+* Improved user experience, particularly on mobile applications, because users only need an email address or mobile phone number to sign up.
-### Passwordless on iOS
+* Enhanced security: Passwords are a major vulnerability as users reuse passwords and are able to share them with others. Passwords are the biggest attack vector and are responsible for a significant percentage of breaches. They also lead to attacks such as credentials stuffing, corporate account takeover, and brute force attacks.
- - [Authenticate users with Universal Login](/connections/passwordless/native-passwordless-universal)
- - [Authenticate users with a one time code via SMS](/connections/passwordless/ios-sms-swift)
- - [Authenticate users with a one time code via e-mail](/connections/passwordless/ios-email-swift)
- - [Authenticate users with Touch ID](/connections/passwordless/ios-touch-id-swift)
- - [Authenticate users with Magic Link](/connections/passwordless/ios-magic-link)
+* Reduces the total cost of ownership, as managing passwords is expensive (implementing password complexity policies, password expiration, password reset processes, password hashing and storing, breached password detection).
-### Passwordless on Android
+## Supported authentication methods
- - [Authenticate users with Universal Login](/connections/passwordless/native-passwordless-universal)
- - [Authenticate users with a one time code via SMS](/connections/passwordless/android-sms)
- - [Authenticate users with a one time code via e-mail](/connections/passwordless/android-email)
- - [Authenticate users with Magic Link](/libraries/lock-android/passwordless-magic-link)
+Auth0 Passwordless connections support one-time-use codes sent via SMS or email, and magic links sent via email.
-### Passwordless API
+
-If you'd like to build your own implementation or understand how this works under the hood, check out the [complete API reference](/auth-api#passwordless).
+### SMS
-## Advanced Topics
+When using passwordless authentication with SMS, users:
- - [Send one time codes via your own SMS Gateway](/connections/passwordless/sms-gateway)
+1. Provide a mobile phone number instead of a username/password combination.
-## Have Questions?
+ 
-You may find the answers on the [Auth0 Passwordless FAQ](/connections/passwordless/faq).
+2. Receive a one-time-use code via SMS.
+
+3. Enter the one-time-use code on the login screen to access the application.
+
+
+
+
+### Email
+
+When using passwordless authentication with email, users:
+
+1. Provide an email address instead of a username/password combination.
+
+
+
+2. Depending on how you have configured your passwordless connection, receive either a one-time-use code or magic link via email.
+
+3. Enter the one-time-use code on the login screen (or click the magic link in the email) to access the application.
+
+
+
+
+
+## Implement Passwordless
+
+To implement passwordless you'll need to make two key decisions:
+
+- Which authentication factor you want to use (SMS or Email with one-time-use code, Email with Magic Link).
+- If you are going to implement authentication using *Embedded Login* or *Universal Login*.
+
+### Authentication Factor
+
+The main driver for picking the authentication factor is user experience, and that depends on your application and its target audience. If the application will run on mobile phones, it is highly likely that users will be able to receive SMS messages. If it's an internal web application that is used in an environment where users cannot have their mobile phones with them, Email would be the only choice.
+
+If you decide to use Email, then you need to decide between an one-time-use code or a magic link. We recommend using one-time-use code as the login flow is more predictable for end users. To learn more refer to the following documents:
+
+ - [Passwordless using Email and one-time-use code](/connections/passwordless/email-otp)
+ - [Passwordless using Email and Magic Links](/connections/passwordless/email-magic-link)
+ - [Passwordless using SMS](/connections/passwordless/sms-otp)
+
+### Implementing Login
+
+Auth0 supports two ways of implementing authentication: *Embedded Login* and *Universal Login*.
+
+The industry is aligned in that Universal Login is the proper way to implement authentication in all apps, but in the case of Native Applications, sometimes customers prefer to implement Embedded Login for UX reasons.
+
+ - [Passwordless Authentication with Universal Login](/connections/passwordless/universal-login)
+ - [Passwordless Authentication with Embedded Login](/connections/passwordless/embedded-login)
+
+## Keep reading
+
+ * [Best practices for Passwordless Authentication](/connections/passwordless/best-practices)
+ * [API Documentation](/connections/passwordless/relevant-api-endpoints)
+ * [Migrating from deprecated Passwordless endpoints](/migrations/guides/migration-oauthro-oauthtoken-pwdless)
diff --git a/articles/connections/passwordless/ios-email-objc.md b/articles/connections/passwordless/ios-email-objc.md
deleted file mode 100644
index a8494d1323..0000000000
--- a/articles/connections/passwordless/ios-email-objc.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: Using Passwordless Authentication on iOS with e-mails - Objective C
-languages:
- - name: Swift
- url: swift
- - name: Objective-C
- url: objc
----
-# Using Passwordless on iOS with Email (Objective C)
-
-
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-<%= include('./_using-lock-ios-email', { language: 'objc' }) %>
diff --git a/articles/connections/passwordless/ios-email-swift.md b/articles/connections/passwordless/ios-email-swift.md
deleted file mode 100644
index aef96f9421..0000000000
--- a/articles/connections/passwordless/ios-email-swift.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: Using Passwordless Authentication on iOS with e-mails - Swift
-languages:
- - name: Swift
- url: swift
- - name: Objective-C
- url: objc
----
-# Using Passwordless on iOS with Email
-
-
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-<%= include('./_using-lock-ios-email', { language: 'swift' }) %>
diff --git a/articles/connections/passwordless/ios-magic-link.md b/articles/connections/passwordless/ios-magic-link.md
deleted file mode 100644
index 28225bad71..0000000000
--- a/articles/connections/passwordless/ios-magic-link.md
+++ /dev/null
@@ -1,80 +0,0 @@
----
-title: Lock iOS v1 Passwordless Magic Links
-description: Using Passwordless Magic Links with Lock for iOS v1
----
-
-# Lock iOS v1: Passwordless with Magic Link
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-Using [Lock v1 for iOS](/libraries/lock-ios/v1), you can implement a Passwordless login flow using Magic Link authentication for your iOS applications.
-
-::: note
-Before beginning this tutorial, [enable Universal Links](/applications/enable-universal-links/) between your iOS application and Auth0 Application.
-:::
-
-## Set Up Universal Link domains for your iOS app
-
-iOS needs to know which domains your application handles. To configure this:
-
-1. Go to your project's Xcode settings page and open the *Capabilities* tab.
-2. Find the *Associated Domains* section, and move the slider (located near the top right) so that it displays **On**. This enables the use of Associated Domains.
-3. Click on the **plus sign** to add your Auth0 Application's domain. You'll need to use the following format: `applinks:${account.namespace}`
-
-
-
-## Pass callbacks to Lock
-
-::: note
-If you've already implemented [Lock v1 for iOS](https://auth0.com/blog/how-to-implement-slack-like-login-on-ios-with-auth0/), you have already configured callbacks to the Auth0 Lock Library.
-:::
-
-In the `AppDelegate` class of your iOS application, include the following code to pass callbacks to Auth0 Lock:
-
-```swift
-
-@UIApplicationMain
-class AppDelegate: UIResponder, UIApplicationDelegate {
-
- var window: UIWindow?
-
- func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
- A0Lock.sharedLock().applicationLaunchedWithOptions(launchOptions)
- return true
- }
-
- func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
- return A0Lock.sharedLock().handleURL(url, sourceApplication: sourceApplication)
- }
-
- func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
- return A0Lock.sharedLock().continueUserActivity(userActivity, restorationHandler:restorationHandler)
- }
-}
-
-```
-
-### Enable Magic Link login strategy
-
-Because the Lock library handles the login flow, you'll indicate that it should use a Magic Link. To do this, you'll place the following code into the view controller that presents the Lock login screen:
-
-```swift
-let lock = A0Lock.sharedLock()
-let controller = lock.newEmailViewController()
-
-controller.useMagicLink = true // <--- ENABLE MAGIC LINKS!
-
-controller.onAuthenticationBlock = { (profile, token) in
- // Do something with profile and token if necessary
- self.dismissViewControllerAnimated(true, completion: { self.performSegueWithIdentifier("UserLoggedIn", sender: self) })
-}
-lock.presentEmailController(controller, fromController: self)
-```
-
-* The `newEmailViewController` creates an email login view controller.
-* Setting `userMagicLink` to `true` tells the email login view controller to use the Magic Link.
-
-### Test notes
-
-* Because Universal Links do not work on iOS simulators, you'll need an iOS-enabled device to test this implementation.
-* When testing, do not use the Gmail app to open the email that contains the Magic Link. Gmail opens links internally or using Chrome, both of which bypass the detection of the Universal Link by iOS.
diff --git a/articles/connections/passwordless/ios-sms-objc.md b/articles/connections/passwordless/ios-sms-objc.md
deleted file mode 100644
index 61e423377a..0000000000
--- a/articles/connections/passwordless/ios-sms-objc.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: Using Passwordless Authentication on iOS with SMS
-languages:
- - name: Swift
- url: swift
- - name: Objective-C
- url: objc
----
-# Using Passwordless on iOS with SMS
-
-
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-<%= include('./_using-lock-ios-sms', { language: 'objc' }) %>
diff --git a/articles/connections/passwordless/ios-sms-swift.md b/articles/connections/passwordless/ios-sms-swift.md
deleted file mode 100644
index e610f3b291..0000000000
--- a/articles/connections/passwordless/ios-sms-swift.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: Using Passwordless Authentication on iOS with SMS in Swift
-languages:
- - name: Swift
- url: swift
- - name: Objective-C
- url: objc
----
-# Using Passwordless on iOS with SMS
-
-
-
-<%= include('../../_includes/_native_passwordless_warning') %>
-
-<%= include('./_using-lock-ios-sms', { language: 'swift' }) %>
diff --git a/articles/connections/passwordless/ios-touch-id-objc.md b/articles/connections/passwordless/ios-touch-id-objc.md
deleted file mode 100644
index d059c4222e..0000000000
--- a/articles/connections/passwordless/ios-touch-id-objc.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: Passwordless Authentication on iOS with Touch ID (Objective-C)
-languages:
- - name: Swift
- url: swift
- - name: Objective-C
- url: objc
----
-# Using Passwordless on iOS with TouchID
-
-
-
-::: warning
-This feature is disabled for new tenants as of June 8th 2017. Any tenant created after that date won't have the necessary legacy [grant types](/applications/application-grant-types) to use Touch ID. This document is offered as reference for older implementations.
-:::
-
-::: note
-For an alternative approach, using the [Credentials Manager](https://github.com/auth0/Auth0.swift/blob/master/Auth0/CredentialsManager.swift) utility in Auth0.swift, refer to [Touch ID Authentication](/libraries/lock-ios/v2/touchid-authentication).
-:::
-
-<%= include('./_using-lock-ios-touchid', { language: 'objc' }) %>
diff --git a/articles/connections/passwordless/ios-touch-id-swift.md b/articles/connections/passwordless/ios-touch-id-swift.md
deleted file mode 100644
index d10be0d905..0000000000
--- a/articles/connections/passwordless/ios-touch-id-swift.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-title: Passwordless Authentication on iOS with Touch ID (Swift)
-connection: iOS Touch ID
-image: /media/connections/touchid.svg
-alias:
- - ios-touchid
- - ios
-seo_alias: ios-touch-id-swift
-languages:
- - name: Swift
- url: swift
- - name: Objective-C
- url: objc
----
-# Using Passwordless on iOS with TouchID
-
-
-
-::: warning
-This feature is disabled for new tenants as of June 8th 2017. Any tenant created after that date won't have the necessary legacy [grant types](/applications/application-grant-types) to use Touch ID. This document is offered as reference for older implementations.
-:::
-
-::: note
-For an alternative approach, using the [Credentials Manager](https://github.com/auth0/Auth0.swift/blob/master/Auth0/CredentialsManager.swift) utility in Auth0.swift, refer to [Touch ID Authentication](/libraries/lock-ios/v2/touchid-authentication).
-:::
-
-<%= include('./_using-lock-ios-touchid', { language: 'swift' }) %>
diff --git a/articles/connections/passwordless/ios.md b/articles/connections/passwordless/ios.md
deleted file mode 100644
index abf7e2d303..0000000000
--- a/articles/connections/passwordless/ios.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: Using Passwordless Authentication on iOS
----
-# Using Passwordless on iOS
-
-
-
-::: warning
-This feature is disabled by default for new tenants as of 8 June 2017. If you would like this feature enabled, please contact support to discuss your use case and prevent the possibility of introducing security vulnerabilities. Please see [Application Grant Types](/applications/application-grant-types) for more information.
-:::
-
-<%= include('./_introduction', { withFingerprint: true }) %>
-
-## Tutorials for iOS
-
- - [Authenticate users with a one-time code via SMS](/connections/passwordless/ios-sms-swift)
- - [Authenticate users with a one-time code via e-mail](/connections/passwordless/ios-email-swift)
- - [Authenticate users with Touch ID](/connections/passwordless/ios-touch-id-swift)
- - [Authenticate users with Magic Link](/connections/passwordless/ios-magic-link)
diff --git a/articles/connections/passwordless/native-passwordless-universal.md b/articles/connections/passwordless/native-passwordless-universal.md
deleted file mode 100644
index 9bd97649fd..0000000000
--- a/articles/connections/passwordless/native-passwordless-universal.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: Passwordless Authentication in Native Applications with Universal Login
-description: Describes how to implement passwordless authentication in native applications, using universal login
----
-# Passwordless Authentication in Native Applications with Universal Login
-
-[Universal Login](/hosted-pages/login) is the only recommended way to set up passwordless authentication in your native application. We recommend using the Auth0 login page for the best experience, security and the fullest array of features.
-
-If you implement passwordless with universal login, the user experience will be as follows:
-
-1. A user clicks login and the Auth0 SDK redirects them to the login page on the web.
-1. At this point, Lock Passwordless will ask them for a phone number or email, whichever type you chose.
-1. The prompt will change to ask them for a code which they will receive by the designated method.
-1. Once they enter the code, the transaction will finish and the user will be redirected to your app along with their credentials.
-
-In this article we will see the steps involved in implementing this flow.
-
-## 1. Set up your connection
-
-To set up the passwordless connection, go to [Dashboard > Connections > Passwordless](${manage_url}/#/connections/passwordless) and turn on either Email or SMS. Then, go to the **Apps** tab and enable the connection for the applications that will be using it.
-
-## 2. Configure your login page
-
-Next, configure your login page. Head over to the [Hosted Pages](${manage_url}/#/login_page) section of your Dashboard. At the top of your the code editor, click the menu entitled **Default Templates** and pick **Lock (Passwordless)** from the list.
-
-## 3. Configure your application
-
-All that remains is to set up your application to call the login page. An easy to follow guide for this process already exists for both Swift and Android. Choose a quickstart below, and follow only the **Login** step. It will guide you on how to call the login page from your application.
-
-* [iOS (Swift) Quickstart](/quickstart/native/ios-swift/00-login)
-* [Android Quickstart](/quickstart/native/android/00-login)
-
-::: note
-The process for invoking universal login from a native app is the same whether `lock-passwordless` will be used inside the login page or not.
-:::
diff --git a/articles/connections/passwordless/regular-web-app-email-code.md b/articles/connections/passwordless/regular-web-app-email-code.md
deleted file mode 100644
index 3e7371aeb2..0000000000
--- a/articles/connections/passwordless/regular-web-app-email-code.md
+++ /dev/null
@@ -1,114 +0,0 @@
----
-title: Using Passwordless Authentication with a one-time code via email on Regular Web Apps
----
-# Passwordless Authentication with a one-time code via e-mail on Regular Web Apps
-
-<%= include('_introduction-email', { isMobile: false }) %>
-
-## Setup
-
-<%= include('_setup-email') %>
-
-<%= include('_setup-callback', {spa:false} )%>
-
-## Implementation
-
-### Use Lock (the Auth0 UI widget)
-
-<%= include('_init-passwordless-lock') %>
-
-Then you can trigger the login using the `callbackURL` option to specify the endpoint that will handle the server-side authentication:
-
-```html
-
-
-
-Login
-```
-
-This will open a dialog that asks the user for their email address:
-
-
-
-Then Auth0 will send an email to the user containing the one-time code:
-
-
-
-Lock will ask for the code that has been emailed to the provided address. The code can then be used as a one-time password to log in:
-
-
-
-Once the user enters the code received by email, Lock will authenticate the user and redirect to the specified `callbackURL`.
-
-::: note
-You can follow any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the server-side authentication callback. A sample application is available in the [Node.js Passwordless Authentication repository](https://github.com/auth0/auth0-node-passwordless-sample) on GitHub.
-:::
-
-### Use your own UI
-
-<%= include('../../_includes/_package', {
- org: 'auth0-samples',
- repo: 'auth0-node-passwordless-sample',
- path: ''
-}) %>
-
-You can perform passwordless authentication in your regular web app with your own custom UI using the [Auth0 JavaScript application library](/libraries/auth0js).
-
-<%= include('_init-auth0js_v9', {redirectUri:true} ) %>
-
-You must provide a way for the user to enter a address to which the email will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
-
-```js
-function sendEmail(){
- var email = $('input.email').val();
-
- webAuth.passwordlessStart({
- connection: 'email',
- send: 'code',
- email: email
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // Hide the input and show the code entry screen
- $('.enter-email').hide();
- $('.enter-code').show();
- });
-}
-```
-
-This will send an email to the provided address. The user must now enter the code they received into your custom UI. Then you can continue with the login as follows (assuming the name of your form inputs as `input.email` and `input.code`):
-
-```js
-function login(){
- var email = $('input.email').val();
- var code = $('input.code').val();
-
- webAuth.passwordlessVerify({
- connection: 'email',
- email: email,
- verificationCode: code
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- });
-};
-```
-
-If authentication is successful, the user will be redirected to the `redirectUri` specified in the Auth0 constructor.
-
-Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/regular-web-app-email-link.md b/articles/connections/passwordless/regular-web-app-email-link.md
deleted file mode 100644
index 448f329716..0000000000
--- a/articles/connections/passwordless/regular-web-app-email-link.md
+++ /dev/null
@@ -1,85 +0,0 @@
----
-title: Using Passwordless Authentication with a magic link via email on Regular Web Apps
----
-# Passwordless Authentication with a magic link via e-mail on Regular Web Apps
-
-<%= include('_introduction-email-magic-link') %>
-
-## Setup
-
-<%= include('_setup-email') %>
-
-<%= include('_setup-callback', {spa:false} ) %>
-
-## Implementation
-
-### Use Lock (the Auth0 UI widget)
-
-<%= include('_init-passwordless-lock') %>
-
-Then you can trigger the login using the `callbackURL` option to specify the endpoint that will handle the authentication on the server-side:
-
-```html
-
-
-Login
-```
-
-This will open a dialog that asks the user for their email address.
-
-
-
-Then Auth0 will send an email to the user containing the magic link. After clicking the link, the user will be signed in to your application automatically and redirected to the specified `callbackURL`.
-
-::: note
-You can follow any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the authentication callback server side. A sample application is available in the [Node.js Passwordless Authentication repository](https://github.com/auth0/auth0-node-passwordless-sample) on GitHub.
-:::
-
-### Use your own UI
-
-<%= include('../../_includes/_package', {
- org: 'auth0-samples',
- repo: 'auth0-node-passwordless-sample',
- path: ''
-}) %>
-
-You can perform passwordless authentication in your regular web app with your own custom UI using the [Auth0 JavaScript application library](/libraries/auth0js).
-
-<%= include('_init-auth0js_v9', {redirectUri:true} ) %>
-
-You must provide a way for the user to enter an email to which the magic link will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
-
-```js
-function sendEmail(){
- var email = $('input.email').val();
-
- webAuth.passwordlessStart({
- connection: 'email',
- send: 'link',
- email: email
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // Hide the input and show a "Check your email for your login link!" screen
- $('.enter-email').hide();
- $('.check-email').show();
- });
-}
-```
-
-This will send an email containing the magic link. After clicking the link, the user will be automatically signed in and redirected to the `redirectUri` which can be specified in the Auth0 constructor.
-
-Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/regular-web-app-sms.md b/articles/connections/passwordless/regular-web-app-sms.md
deleted file mode 100644
index 6849d73164..0000000000
--- a/articles/connections/passwordless/regular-web-app-sms.md
+++ /dev/null
@@ -1,115 +0,0 @@
----
-title: Using Passwordless Authentication in a Regular Web App with SMS
----
-# Authenticate users with a one-time code via SMS in a Regular Web App
-
-<%= include('_introduction-sms', { isMobile: false }) %>
-
-## Setup
-
-<%= include('_setup-sms-twilio') %>
-
-<%= include('_setup-callback', {spa:false} ) %>
-
-## Implementation
-
-### Use Lock (the Auth0 UI widget)
-
-<%= include('_init-passwordless-lock') %>
-
-Then you can trigger the login widget with the following code:
-
-```html
-
-
-Login
-```
-
-This will open a dialog that asks the user for their phone number.
-
-
-
-Then Auth0 will use Twilio to send an SMS to the user containing the one-time code:
-
-
-
-Lock will ask for the code that has been sent to the provided number via SMS. The code can then be used as a one-time password to log in:
-
-
-
-Once the user enters the code received via SMS, Lock will authenticate the user and redirect to the specified `callbackURL`.
-
-::: note
-You can follow any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the server-side authentication callback.
-:::
-
-### Use your own UI
-
-<%= include('../../_includes/_package', {
- org: 'auth0-samples',
- repo: 'auth0-node-passwordless-sample',
- path: ''
-}) %>
-
-You can perform passwordless authentication in your regular web app with your own custom UI using the [Auth0 JavaScript application library](/libraries/auth0js).
-
-<%= include('_init-auth0js_v9', {redirectUri:true} ) %>
-
-You must provide a way for the user to enter a phone number to which the SMS will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.phone-number`):
-
-```js
-function sendSMS(){
- var phone = $('input.phone-number').val();
-
- webAuth.passwordlessStart({
- connection: 'sms',
- send: 'code',
- phoneNumber: phone
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // Hide the input and show the code entry screen
- $('.enter-phone').hide();
- $('.enter-code').show();
- });
-}
-```
-
-This will send an SMS to the provided phone number. The user must now enter the code they received into your custom UI. Then you can continue with the login as follows (assuming the name of your form inputs as `input.phone-number` and `input.code`):
-
-```js
-function login(){
- var phone = $('input.phone-number').val();
- var code = $('input.code').val();
-
- webAuth.passwordlessVerify({
- connection: 'sms',
- phoneNumber: phone,
- verificationCode: code
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- });
-};
-```
-
-If authentication is successful, the user will be redirected to the `redirectUri` specified in the Auth0 constructor.
-
-::: note
-You can follow up with any of the [Regular Web App Quickstarts](/quickstart/webapp) to see how to handle the authentication callback on the server-side.
-:::
-
-Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/regular-web-app.md b/articles/connections/passwordless/regular-web-app.md
deleted file mode 100644
index 29b7cbfb1c..0000000000
--- a/articles/connections/passwordless/regular-web-app.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: Using Passwordless Authentication on a Regular Web Application
----
-# Using Passwordless Authentication on a Regular Web App
-
-<%= include('./_introduction', { withFingerprint: false }) %>
-
-## Tutorials for Regular Web Applications
-
- - [Authenticate users with a one-time code via SMS](/connections/passwordless/regular-web-app-sms)
- - [Authenticate users with a one-time code via e-mail](/connections/passwordless/regular-web-app-email-code)
- - [Authenticate users with a magic link via e-mail](/connections/passwordless/regular-web-app-email-link)
diff --git a/articles/connections/passwordless/sample-use-cases-rules.md b/articles/connections/passwordless/sample-use-cases-rules.md
new file mode 100644
index 0000000000..c8e12ff952
--- /dev/null
+++ b/articles/connections/passwordless/sample-use-cases-rules.md
@@ -0,0 +1,52 @@
+---
+title: Sample Use Cases - Rules with Passwordless Authentication
+description: See examples using rules with passwordless connections.
+topics:
+ - connections
+ - passwordless
+ - rules
+contentType: concept
+useCase: customize-connections
+---
+# Sample Use Cases: Rules with Passwordless Authentication
+
+With [rules](/rules), you can handle more complicated cases than is possible with [passwordless connections](/connections/passwordless) alone. For instance, you can add extra precautions to further ensure possession of an email address or device.
+
+## Require Multi-factor Authentication for users who are outside the corporate network
+
+Let's say you want to require [multi-factor authentication (MFA)](/multifactor-authentication) for any users who are accessing the application using a passwordless connection from outside your corporate network.
+
+Using a rule, you can check whether a user is authenticating using a passwordless method (`sms`, `email`) and if their session IP falls outside of the designated corporate network, prompt them for a second authentication factor.
+
+::: note
+You could also trigger this rule based on other criteria, such as whether the current IP matches the user's IP allowlist or whether geolocating the user reveals they are in a different country from the one listed in their user profile.
+:::
+
+To do this, you would [create the following rule](/dashboard/guides/rules/create-rules):
+
+```js
+function(user, context, callback) {
+
+ const ipaddr = require('ipaddr.js');
+ const corp_network = "192.168.1.134/26";
+ const current_ip = ipaddr.parse(context.request.ip);
+
+ // is auth method passwordless and IP outside corp network?
+ const passwordlessOutside = context.authentication.methods.find(
+ (method) => (
+ ((method.name === 'sms') || (method.name === 'email')) &&
+ (!current_ip.match(ipaddr.parseCIDR(corp_network)))
+ )
+ );
+
+ // if yes, then require MFA
+ if (passwordlessOutside) {
+ context.multifactor = {
+ provider: 'any',
+ allowRememberBrowser: false
+ };
+ }
+
+ callback(null, user, context);
+}
+```
diff --git a/articles/connections/passwordless/sms-gateway.md b/articles/connections/passwordless/sms-gateway.md
deleted file mode 100644
index 6ad0321e2d..0000000000
--- a/articles/connections/passwordless/sms-gateway.md
+++ /dev/null
@@ -1,114 +0,0 @@
----
-title: Send one time codes via your own SMS Gateway
----
-
-# Send one time codes via your own SMS Gateway
-
-By default the SMS connection will use Twilio to send the one time code. If you already have your own infrastructure to send text messages cannot or might not want to use Twilio.
-
-Instead you'll want your own infrastructure to handle the delivery of these one time codes.
-
-## Configure your SMS Gateway
-
-The configuration of your own SMS Gateway currently needs to happen through the Management API. You would first need to get your connections (strategy: `sms`) from the [GET connections endpoint](/api/v2#!/Connections/get_connections).
-
-This will return your SMS connection with your Twilio settings:
-
-```
-[
- {
- "id": "con_...",
- "options": {
- "strategy": "sms",
- "twilio_sid": "...",
- "twilio_token": "...",
- "from": "+1 234 567",
- "template": "Your verification code is: @@password@@",
- "brute_force_protection": true,
- "disable_signup": false,
- "name": "sms",
- "syntax": "md_with_macros",
- "totp": {
- "time_step": 300,
- "length": 6
- }
- },
- "strategy": "sms",
- "name": "sms",
- "enabled_clients": [
- ...
- ]
- }
-]
-```
-
-You can now modify the options of the connection:
-
- - `provider`: Set this to `sms_gateway`
- - `gateway_url`: Set this to the URL of your SMS Gateway. Note that Auth0 must be able to reach it in order for this to work.
-
-```
-{
- "options": {
- "strategy": "sms",
- "provider": "sms_gateway",
- "gateway_url": "{URL_OF_YOUR_GATEWAY}",
- "from": "+1 234 567",
- "template": "Your verification code is: @@password@@",
- "brute_force_protection": true,
- "disable_signup": false,
- "name": "sms",
- "syntax": "md_with_macros",
- "totp": {
- "time_step": 300,
- "length": 6
- }
- }
-}
-```
-
-You can then send the updated configuration to the Management API using the [PATCH connections endpoint](/api/v2#!/Connections/patch_connections_by_id).
-
-After updating the connection for any user that signs up or authenticates using the Passwordless SMS connection the following payload will be sent to your SMS gateway:
-
-```
-{
- "recipient": "+1 399 999",
- "body": "Your verification code is: 12345",
- "sender": "+1 234 567",
-}
-```
-
-## Configure an authenticated SMS Gateway
-
-The previous settings assume your SMS Gateway accepts non-authenticated requests. The `sms_gateway` provider also allows you to configure token based authentication (using `gateway_authentication`):
-
-```
-{
- "options": {
- "strategy": "sms",
- "provider": "sms_gateway",
- "gateway_url": "{URL_OF_YOUR_GATEWAY}",
- "gateway_authentication": {
- "method": "bearer",
- "subject": "urn:Auth0",
- "audience": "urn:MySmsGateway",
- "secret": "MySecretToSignTheToken"
- },
- "from": "+1 234 567",
- "template": "Your verification code is: @@password@@",
- "brute_force_protection": true,
- "disable_signup": false,
- "name": "sms",
- "syntax": "md_with_macros",
- "totp": {
- "time_step": 300,
- "length": 6
- }
- }
-}
-```
-
-With this configuration, when the payload is sent to the SMS Gateway a JWT will be added to the `Authorization` header which contains a token with the `subject` and `audience` configured in the connection and signed with the `secret`.
-
-Additionally, if your secret is base64 url encoded you can set `options.secret_base64_encoded` to `true`.
diff --git a/articles/connections/passwordless/sms.md b/articles/connections/passwordless/sms.md
deleted file mode 100644
index 23715a6922..0000000000
--- a/articles/connections/passwordless/sms.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-title: SMS Passwordless Authentication
-connection: SMS
-url: /connections/passwordless/sms
-image:
-alias:
- - sms
-seo_alias: sms
----
-
-# Authenticate users with a one-time code via SMS
-
-<%= include('./_introduction-sms', { isMobile: false }) %>
-
-## Setup
-
-<%= include('./_setup-sms-twilio') %>
-
-## Web Tutorials
-
-- [Single-page Applications](/connections/passwordless/spa-sms)
-- [Regular Web Applications](/connections/passwordless/regular-web-app-sms)
-
-## Mobile Tutorials
-
- - [iOS](/connections/passwordless/ios-sms-swift)
- - [Android](/connections/passwordless/android-sms)
diff --git a/articles/connections/passwordless/spa-email-code.md b/articles/connections/passwordless/spa-email-code.md
deleted file mode 100644
index b4f6858420..0000000000
--- a/articles/connections/passwordless/spa-email-code.md
+++ /dev/null
@@ -1,145 +0,0 @@
----
-title: Using Passwordless Authentication with a one-time code via email on SPA
-description: Learn how to authenticate users with a one-time-code using email in a Single Page Application (SPA).
----
-# Using Passwordless Authentication in SPA with Email
-
-<%= include('_introduction-email', { isMobile: false }) %>
-
-## Setup
-
-<%= include('_setup-email') %>
-
-<%= include('_setup-cors') %>
-
-## Implementation
-
-### Use Lock (the Auth0 UI widget)
-
-<%= include('_init-passwordless-lock') %>
-
-Then you can trigger the login with the following code:
-
-```html
-
-
-Login
-```
-
-First, this will open a dialog that asks the user for their email address:
-
-
-
-Then Auth0 will send an email to the user containing the one-time code:
-
-
-
-Lock will ask for the code that has been emailed to the provided address. The code can then be used as a one-time password to log in.
-
-
-
-Once the user enters the code received by email, Lock will authenticate them and call the callback function where the `id_token` and profile will be available.
-
-### Use your own UI
-
-<%= include('../../_includes/_package', {
- org: 'auth0-samples',
- repo: 'auth0-jquery-passwordless-sample',
- path: ''
-}) %>
-
-You can perform passwordless authentication in your SPA with your own custom UI using the [Auth0 JavaScript SDK](/libraries/auth0js).
-
-<%= include('_init-auth0js_v9', {redirectUri:true} ) %>
-
-Be sure to provide a `redirectUri` and to set the `responseType: 'token'`.
-
-You must provide a way for the user to enter a address to which the email will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
-
-```js
-function sendEmail(){
- var email = $('input.email').val();
-
- webAuth.passwordlessStart({
- connection: 'email',
- send: 'code',
- email: email
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // Hide the input and show the code entry screen
- $('.enter-email').hide();
- $('.enter-code').show();
- });
-}
-```
-
-This will send an email to the provided address. The user must now enter the code they received into your custom UI. Then you can continue with the login as follows (assuming the name of your form inputs as `input.email` and `input.code`):
-
-```js
-function login(){
- var email = $('input.email').val();
- var code = $('input.code').val();
-
- webAuth.passwordlessVerify({
- connection: 'email',
- email: email,
- verificationCode: code
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // If successful, save the user's token and proceed
- });
-};
-```
-
-The `passwordlessVerify` method will verify the Passwordless transaction, then redirect the user back to the `redirectUri` that was set. You will then need to parse the URL hash in order to acquire the token, and then call the `client.userInfo` method to acquire your user's information, as in the following example:
-
-```js
-$(document).ready(function() {
- if(window.location.hash){
- webAuth.parseHash(window.location.hash, function(err, authResult) {
- if (err) {
- return console.log(err);
- } else if (authResult){
- localStorage.setItem('accessToken', authResult.accessToken);
- webAuth.client.userInfo(authResult.accessToken, function(err, user) {
- if (err){
- console.log('err',err);
- alert('There was an error retrieving your profile: ' + err.message);
- } else {
- // Hide the login UI, show a user profile element with name and image
- $('.login-box').hide();
- $('.logged-in-box').show();
- localStorage.setItem('user', user);
- $('.nickname').text(user.nickname);
- $('.avatar').attr('src', user.picture);
- }
- });
- }
- });
- }
-});
-```
-
-Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/spa-email-link.md b/articles/connections/passwordless/spa-email-link.md
deleted file mode 100644
index 1b8a6f0def..0000000000
--- a/articles/connections/passwordless/spa-email-link.md
+++ /dev/null
@@ -1,103 +0,0 @@
----
-title: Using Passwordless Authentication with a Magic Link via email on SPA
----
-# Authenticate users with a Magic Link via e-mail on SPA
-
-<%= include('_introduction-email-magic-link') %>
-
-## Setup
-
-<%= include('_setup-email') %>
-
-<%= include('_setup-callback', {spa:true} ) %>
-
-## Implementation
-
-### Use Lock (the Auth0 UI widget)
-
-<%= include('_init-passwordless-lock') %>
-
-Then you can trigger the passwordless authentication using a magic link with the following code:
-
-```html
-
-
-
-
-Login
-```
-
-The user will receive an email with the magic link. Once the user clicks on this link, Auth0 will handle the authentication and redirect back to the application.
-
-::: note
-You can follow any of the [Single Page App Quickstarts](/quickstart/spa) to see more about using Auth0.js in a SPA.
-:::
-
-### Use your own UI
-
-<%= include('../../_includes/_package', {
- org: 'auth0-samples',
- repo: 'auth0-jquery-passwordless-sample',
- path: ''
-}) %>
-
-You can perform passwordless authentication with a magic link in your single-page application using your own UI with the [Auth0 JavaScript client library](/libraries/auth0js).
-
-<%= include('_init-auth0js_v9', {redirectUri:true} ) %>
-
-You must provide a way for the user to enter an email to which the magic link will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.email`):
-
-```js
-function sendEmail(){
- var email = $('input.email').val();
-
- webAuth.passwordlessStart({
- connection: 'email',
- send: 'link',
- email: email
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // Hide the input and show a "Check your email for your login link!" screen
- $('.enter-email').hide();
- $('.check-email').show();
- });
-}
-```
-
-This will send an email containing the magic link. After clicking the link, the user will be automatically signed in and redirected to the `redirectUri` which can be specified in the Auth0 constructor, where you will need to parse the token with `webAuth.parseHash`:
-
-```js
-//parse hash on page load
-$(document).ready(function(){
- webAuth.parseHash(window.location.hash, function(err, authResult) {
- if (err) {
- return console.log(err);
- }
-
- webAuth.client.userInfo(authResult.accessToken, function(err, user) {
- // Now you have the user's information
- });
- });
-});
-```
-
-Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/spa-sms.md b/articles/connections/passwordless/spa-sms.md
deleted file mode 100644
index f13cccae43..0000000000
--- a/articles/connections/passwordless/spa-sms.md
+++ /dev/null
@@ -1,151 +0,0 @@
----
-title: Using Passwordless Authentication in SPA with SMS
-description: Learn how to authenticate users with a one-time-code using SMS in a Single Page Application (SPA).
----
-# Using Passwordless Authentication in SPA with SMS
-
-<%= include('_introduction-sms', { isMobile: true }) %>
-
-## Setup
-
-<%= include('_setup-sms-twilio') %>
-
-<%= include('_setup-cors') %>
-
-## Implementation
-
-### Use Lock
-
-<%= include('_init-passwordless-lock') %>
-
-You can then trigger the login widget with the following code:
-
-```html
-
-
-Login
-```
-
-This will open a dialog that asks the user for their phone number.
-
-
-
-Then Auth0 will use Twilio to send to the user an SMS containing the one-time code:
-
-
-
-Lock will ask for the code that has been sent via SMS to the provided number. The code can then be used as a one-time password to log in:
-
-
-
-If the code is correct, the user will be authenticated. This will trigger the `authenticated` event where the ID Token and Access Token will be available. Then the user will be allowed to continue to the authenticated part of the application.
-
-### Use your own UI
-
-<%= include('../../_includes/_package', {
- org: 'auth0-samples',
- repo: 'auth0-jquery-passwordless-sample',
- path: ''
-}) %>
-
-You can perform passwordless authentication in your SPA with your own custom UI using the [Auth0 JavaScript client library](/libraries/auth0js).
-
-First, initialize Auth0.js. Be sure to provide a `redirectUri` and to set the `responseType: 'token id_token'`.
-
-```js
-var webAuth = new auth0.WebAuth({
- clientID: '${account.clientId}',
- domain: '${account.namespace}',
- redirectUri: 'http://example.com',
- responseType: 'token id_token'
-});
-```
-
-You must provide a way for the user to enter a phone number to which the SMS will be sent. Then you can begin the passwordless authentication as follows (assuming the name of your form input as `input.phone-number`):
-
-```js
-function sendSMS(){
- var phone = $('input.phone-number').val();
-
- webAuth.passwordlessStart({
- connection: 'sms',
- send: 'code',
- phoneNumber: phone
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // Hide the input and show the code entry screen
- $('.enter-phone').hide();
- $('.enter-code').show();
- });
-}
-```
-
-This will send an SMS to the provided phone number. The user must now enter the code they received into your custom UI. Then you can continue with the login as follows (assuming the name of your form inputs as `input.phone-number` and `input.code`):
-
-```js
-function login(){
- var phone = $('input.phone-number').val();
- var code = $('input.code').val();
-
- webAuth.passwordlessLogin({
- connection: 'sms',
- phoneNumber: phone,
- verificationCode: code
- }, function (err,res) {
- if (err) {
- // Handle error
- }
- // If successful, save the user's token and proceed
- });
-};
-```
-
-The `passwordlessLogin` method will verify the Passwordless transaction, then redirect the user back to the `redirectUri` that was set. You will then need to parse the URL hash in order to acquire the token, and then call the `client.userInfo` method to acquire your user's information, as in the following example:
-
-```js
-$(document).ready(function() {
- if(window.location.hash){
- webAuth.parseHash(window.location.hash, function(err, authResult) {
- if (err) {
- return console.log(err);
- } else if (authResult){
- localStorage.setItem('accessToken', authResult.accessToken);
- webAuth.client.userInfo(authResult.accessToken, function(err, user) {
- if (err){
- console.log('err',err);
- alert('There was an error retrieving your profile: ' + err.message);
- } else {
- // Hide the login UI, show a user profile element with name and image
- $('.login-box').hide();
- $('.logged-in-box').show();
- localStorage.setItem('user', user);
- $('.nickname').text(user.nickname);
- $('.avatar').attr('src', user.picture);
- }
- });
- }
- });
- }
-});
-```
-
-Check out the [Auth0.js SDK reference documentation](/libraries/auth0js) for more information.
diff --git a/articles/connections/passwordless/spa.md b/articles/connections/passwordless/spa.md
deleted file mode 100644
index 9e0c4fa6e6..0000000000
--- a/articles/connections/passwordless/spa.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: Using Passwordless Authentication on a Single Page Application
----
-# Using Passwordless Authentication on a SPA
-
-
-
-<%= include('./_introduction', { withFingerprint: false }) %>
-
-## Tutorials for Single-page Applications
-
- - [Authenticate users with a one-time code via SMS](/connections/passwordless/spa-sms)
- - [Authenticate users with a one-time code via e-mail](/connections/passwordless/spa-email-code)
- - [Authenticate users with a magic link via e-mail](/connections/passwordless/spa-email-link)
-
-::: note
-Sample applications are available in the [jQuery Passwordless Authentication repository](https://github.com/auth0/auth0-jquery-passwordless-sample) on GitHub.
-:::
diff --git a/articles/connections/passwordless/universal-login.md b/articles/connections/passwordless/universal-login.md
new file mode 100644
index 0000000000..2cb64289ec
--- /dev/null
+++ b/articles/connections/passwordless/universal-login.md
@@ -0,0 +1,16 @@
+---
+title: Passwordless Authentication with Universal Login
+description: Passwordless Authentication with Universal Login
+toc: true
+topics:
+ - connections
+ - passwordless
+ - authentication
+---
+# Passwordless Authentication with Universal Login
+
+[Universal Login](/universal-login) is Auth0's implementation of the login flow. Each time a user needs to prove their identity, your applications redirect to Universal Login and Auth0 will do what is needed to guarantee the user's identity. It's the preferred way to implement Passwordless Authentication.
+
+To implement Passwordless Authentication in Universal Login you need to customize the login page's HTML. To learn how to do it, please refer to [Configure Universal Login with Passwordless](/dashboard/guides/universal-login/configure-login-page-passwordless).
+
+To integrate Universal Login in your application, please refer to our [Quickstarts](/quickstarts), where you'll find complete examples for all application types and popular platforms.
diff --git a/articles/connections/passwordless/use-sms-gateway-passwordless.md b/articles/connections/passwordless/use-sms-gateway-passwordless.md
new file mode 100644
index 0000000000..14b0df73e8
--- /dev/null
+++ b/articles/connections/passwordless/use-sms-gateway-passwordless.md
@@ -0,0 +1,164 @@
+---
+title: Set Up Custom SMS Gateway for Passwordless Connections
+topics:
+ - connections
+ - passwordless
+ - sms
+contentType: how-to
+useCase: customize-connections
+---
+# Set Up Custom SMS Gateway for Passwordless Connections
+
+This guide will show you how to use a custom SMS gateway to send out your one-time-use codes.
+
+By default, [Passwordless SMS connections](/connections/passwordless#supported-authentication-methods) use [Twilio](https://www.twilio.com/) to send out one-time use codes. However, if you have a custom SMS gateway, you can modify your connection to use that instead.
+
+::: note
+Auth0 does **not** support basic SMS authentication.
+:::
+
+1. Set up a SMS passwordless connection. To learn how, see [Set Up Passwordless Connections](/connections/passwordless#implement-passwordless).
+
+2. Get an [Access Token for Management API](/api/management/v2/tokens). You will need this to make calls to the Management API to update your Passwordless connection.
+
+3. Use the [GET Connections](/api/management/v2#!/Connections/get_connections) endpoint to retrieve information about the connections associated with your tenant. More specifically, you need to get the ID for your Passwordless SMS connection so that you can use it in a later API call that updates the connection itself.
+
+ Be sure to replace `ACCESS_TOKEN` with the token you obtained in step 1 before making the following call to the Management API:
+
+```har
+{
+ "method": "GET",
+ "url": "https://your-auth0-tenant.com/api/v2/connections",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer YOUR_ACCESS_TOKEN_HERE" }
+ ]
+}
+```
+
+ The response from the endpoint will be an array of objects. Each object represents one connection affiliated with your tenant.
+
+4. Identify your connection ID. You can find the ID associated with your Passwordless connection by reviewing the array of objects you returned from the [GET Connections](/api/management/v2#!/Connections/get_connections) endpoint in step 2.
+
+ To find the specific object for your Passwordless connection, you can search for the `"name": "sms"` property. Notice that the connection currently displays the Twilio information you provided during the setup process.
+
+```json
+[
+ {
+ "id": "con_UX85K7K0N86INi9U",
+ "options": {
+ "disable_signup": false,
+ "name": "sms",
+ "twilio_sid": "TWILIO_SID",
+ "twilio_token": "TWILIO_AUTH_TOKEN",
+ "from": "+15555555555",
+ "syntax": "md_with_macros",
+ "template": "Your SMS verification code is: @@password@@",
+ "totp": {
+ "time_step": 300,
+ "length": 6
+ },
+ "messaging_service_sid": null,
+ "brute_force_protection": true
+ },
+ "strategy": "sms",
+ "name": "sms",
+ "is_domain_connection": false,
+ "realms": [
+ "sms"
+ ],
+ "enabled_clients": []
+ }
+]
+```
+
+5. Update the connection. You can do this by making a PATCH call to the [Update a Connection](/api/management/v2#!/Connections/patch_connections_by_id) endpoint. More specifically, you'll be updating the connections `options` object to provide information about the SMS Gateway.
+
+ **You must send the entire `options` object with each call; otherwise, you will overwrite the existing data that is not included in subsequent calls.**
+
+ Make the following changes:
+
+ * Remove both the `twilio_sid` and `twilio_token` parameters
+ * Add the `provider` parameter, and set it to `sms_gateway`)
+ * Add the `gateway_url` parameter, and set it to the URL of your SMS gateway. Auth0 **must** be able to reach this URL for it to use your gateway to send messages on your behalf)
+
+ Your payload will look something like the following:
+
+```json
+{
+ "options": {
+ "strategy": "sms",
+ "provider": "sms_gateway",
+ "gateway_url": "URL_OF_YOUR_GATEWAY",
+ "from": "+1 234 567",
+ "template": "Your verification code is: @@password@@",
+ "brute_force_protection": true,
+ "forward_req_info": "true",
+ "disable_signup": false,
+ "name": "sms",
+ "syntax": "md_with_macros",
+ "totp": {
+ "time_step": 300,
+ "length": 6
+ }
+ },
+ "is_domain_connection": false,
+ "enabled_clients": []
+}
+```
+
+## Authenticated requests
+
+If your SMS Gateway accepts authenticated requests that are token-based, you can add the following to your `options` object:
+
+```json
+"gateway_authentication": {
+ "method": "bearer",
+ "subject": "urn:Auth0",
+ "audience": "urn:MySmsGateway",
+ "secret": "MySecretToSignTheToken",
+ "secret_base64_encoded": false
+}
+```
+
+When you include `gateway_authentication` in your **options** object, Auth0 adds a [JSON Web Token](/tokens/concepts/jwts) to the `Authorization` header whenever it sends requests to your SMS gateway. The token contains the `gateway_authentication.subject` and `gateway_authentication.audience` values, and is signed with `gateway_authentication.secret`.
+
+If your secret is base64-url-encoded, set `secret_base64_encoded` to `true`.
+
+6. Once you have updated your connection, Auth0 will send the following to your SMS Gateway every time a user signs up or logs in with your Passwordless connection.
+
+```json
+{
+ "recipient": "+1 399 999",
+ "body": "Your verification code is: 12345",
+ "sender": "+1 234 567"
+}
+```
+
+If you set the `forward_req_info` property in the ****options** object to `true`, the gateway will also receive information from the HTTP request that initiated the Passwordless process. This includes the IP address of the client calling `/passwordless/start` and its User Agent.
+
+```json
+{
+ "recipient": "+1 399 999",
+ "body": "Your verification code is: 12345",
+ "sender": "+1 234 567",
+ "req" : {
+ "ip" : "167.56.227.117",
+ "user-agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36"
+ }
+}
+```
+
+## Error handling
+
+Auth0 will only consider the HTTP code returned from the SMS Gateway; it ignores the rest of the response (e.g., response body and response type).
+
+If the SMS Gateway returns an HTTP code other than 200, the `/passwordless/start` endpoint will return an HTTP 400 code and a response the looks like the following:
+
+```
+{
+ "error":"sms_provider_error",
+ "error_description":"Unexpected response while calling the SMS gateway: "}
+}
+```
+
+If the SMS Gateway returns HTTP 401, the `error_description` will be **Authentication failed while calling the SMS gateway: 401**. (Please note that the error description verbiage is subject to change at any time.)
diff --git a/articles/connections/passwordless/user-guide.md b/articles/connections/passwordless/user-guide.md
deleted file mode 100644
index 5e186ed750..0000000000
--- a/articles/connections/passwordless/user-guide.md
+++ /dev/null
@@ -1,81 +0,0 @@
-# User Guide: Passwordless
-
-If you are using an app that allows for **Passwordless** authentication, you can register using either your **email address** or your **mobile phone number** instead of a login/password combination. Depending on which piece of information you provide, you will then access the app using a link that has been emailed to you or by providing a code that has been emailed or sent to you via SMS.
-
-* [Register and Authenticate Using Email](#register-and-authenticate-using-email)
-* [Register and Authenticate Using SMS](#register-and-authenticate-using-sms)
-* [Troubleshooting](#troubleshooting)
-
-## Register and Authenticate Using Email
-
-
-
-If you provide your **email address**, you will receive an email containing either:
-
-* a link you click on to authenticate yourself, or;
-* a code you provide to the app to authenticate yourself.
-
-### Authentication Using a Magic Link Received via Email
-
-You may opt to register and authenticate yourself using a magic link sent via email. Upon receipt, you will need to click on the link to access the app.
-
-
-
-### Authentication Using a One-time Use Code Received via Email
-
-You may opt to register and authenticate yourself using a one-time use code that you receive via email.
-
-
-
-Once received, you can return to the app to enter the code and authenticate yourself.
-
-
-
-## Register and Authenticate Using SMS
-
-
-
-If you provide your **mobile phone number**, you will receive a code that you will provide to the app to validate yourself.
-
-
-
-The code can then be used as a one-time password to log in.
-
-
-
-## Troubleshooting
-
-The following section contains troubleshooting information that might be useful to you.
-
-### Can I share my password with others?
-
-No, because Passwordless authentication removes the need for and use of passwords.
-
-### How long is the one-time use code/link valid?
-
-The amount of time the one-time use authentication code/link is valid can be set and changed by your app's administrator. It is unlikely, however, that the code/link is valid for a very long period of time, so you should use it as soon as possible.
-
-### What if I am using multiple devices?
-
-If you've requested your authentication links or codes via email, you can use any device that is capable of accessing that email account. You simply need to log in to your email account to get the required information and then provide the information when attempting to access the app.
-
-If the device you're using doesn't have access to the required email account, you can forward the email to an account accessible using that device.
-
-If you are requesting an authentication code via SMS message, you can use any device that will receive messages sent to the phone number associated with your account. Once you have that information, you will be able to provide the code to gain access to the application.
-
-### What happens if I don't receive the authentication emails/SMS messages I requested?
-
-If you do not receive your requested email or SMS message, please do not request a new one. Instead, check the following:
-
-#### Email
-
-* Did the email get filed into your junk/spam folder?
-* Has there been some type of server delay preventing you from receiving your email?
-
-### SMS Message
-
-* Do you have the connectivity to receive messages?
-
-### What happens if I request and receive multiple authentication emails and/or SMS messages?
-
-If you accidentally request more than one email or SMS message containing magic links or authentication codes, the last **five** codes will be valid. Once you successfully log in using any of the codes/links, **all** of the existing codes/links will be invalidated.
diff --git a/articles/connections/social/37signals.md b/articles/connections/social/37signals.md
deleted file mode 100644
index 6bc36e6bd6..0000000000
--- a/articles/connections/social/37signals.md
+++ /dev/null
@@ -1,41 +0,0 @@
----
-title: Connect your app to 37Signals
-connection: Basecamp
-image: /media/connections/basecamp.png
-alias:
- - basecamp
- - thirtysevensignals
-seo_alias: 37signals
-description: How to obtain a Client Id and Client Secret for 37Signals.
-toc: true
----
-
-# Connect your app to 37Signals
-
-To configure a 37Signals OAuth2 connection, you will need to register your Auth0 tenant on the [37Signals Integration Portal](https://integrate.37signals.com/).
-
-## 1. Register a new App
-
-Log into the Integration Portal. Select **New Application** and enter some general information about your app (name, website, logo) on first page:
-
-
-
-## 2. Define the scope of access and enter your callback URL
-
-On the next page, select which 37Signals applications you want to access, and enter your Auth0 callback URL in the **Redirect URI** field:
-
- https://${account.namespace}/login/callback
-
-
-
-## 3. Generate your *Client Id* and *Client Secret*
-
-Once your app is registered, a `Client Id` and `Client Secret` are generated for you.
-
-
-
-Go to your Auth0 Dashboard and select **Connections > Social**, then choose **37Signals**. Copy the `Client Id` and `Client Secret` from the Integration Portal into the fields on this page.
-
-
-
-<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/amazon.md b/articles/connections/social/amazon.md
index 613cdd4993..4d135ba0b4 100644
--- a/articles/connections/social/amazon.md
+++ b/articles/connections/social/amazon.md
@@ -1,49 +1,28 @@
---
-title: Connect your app to Amazon
+title: Connect Apps to Amazon
connection: Amazon Web Services
image: /media/connections/amazon.png
alias:
- aws
- amazon-web-services
seo_alias: amazon
-index: 9
-description: How to obtain a Client Id and Client Secret for Amazon.
toc: true
+public: true
+index: 1
+description: Learn how to add login functionality to your app with Amazon. You will need to obtain a Client Id and Client Secret for Amazon.
+topics:
+ - connections
+ - social
+ - amazon
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Amazon
-
-To configure an Amazon connection with Auth0, you will need to register your app on the Amazon portal.
-
-## 1. Add a new Application
-Log into [Login with Amazon](http://login.amazon.com) and select **App Console**.
-
-
-
-## 2. Register a new application
-
-Click on the **Register New Application** button and enter a **Name**, **Description**, and **Privacy Notice URL** for your app. Click **Save**.
-
-
-
-## 3. Enter your callback URL
-
-Expand the **Web Settings** section. Enter your Auth0 JavaScript origin in the **Allowed JavaScript Origins** field and callback URLs in the **Allowed Return URLs** field. The JavaScript origin address for your app should be:
-
-```text
-https://${account.namespace}/
-```
-
-and the callback address for your app should be:
-
-```text
-https://${account.namespace}/login/callback
-```
-
-## 4. Copy your Client Id and Client Secret
-
-Go to your Auth0 Dashboard and select **Connections > Social**, then choose **Amazon**. Copy the `Client Id` and `Client Secret` from the **Web Settings** of your app on Amazon into the fields on this page on Auth0.
-
-
-
+<%= include('../../../snippets/social/amazon/0') %>
+<%= include('../../../snippets/social/amazon/1') %>
+<%= include('../../../snippets/social/amazon/2') %>
+<%= include('../../../snippets/social/amazon/3') %>
+<%= include('../../../snippets/social/amazon/4') %>
+<%= include('../../../snippets/social/amazon/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/aol.md b/articles/connections/social/aol.md
deleted file mode 100644
index 1e2f9fcf2d..0000000000
--- a/articles/connections/social/aol.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: Connect your app to AOL Reader
-connection: AOL Reader
-image: /media/connections/aol.png
-seo_alias: aol
-description: How to obtain a Client Id and Client Secret for AOL Reader.
----
-
-# Connect your app to AOL Reader
-
-To configure an AOL Reader connection with Auth0, contact [AOL Reader Support](http://help.reader.aol.com/knowledgebase) and provide the following information:
-
-* Your name
-* Your e-mail address
-* The name of your app
-* Your callback URL:
-
- `https://${account.namespace}/login/callback`
-
-<%= include('../_quickstart-links.md') %>
\ No newline at end of file
diff --git a/articles/connections/social/apple-native.md b/articles/connections/social/apple-native.md
new file mode 100644
index 0000000000..f633400742
--- /dev/null
+++ b/articles/connections/social/apple-native.md
@@ -0,0 +1,91 @@
+---
+title: Add Sign In with Apple to Native iOS Apps
+connection: Apple Native
+image: /media/connections/apple.png
+public: true
+description: Learn how to add native login functionality to your native app with Apple.
+topics:
+ - authentication
+ - connections
+ - social
+ - apple
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
+---
+# Add Sign In with Apple to Native iOS Apps
+
+You can add functionality to your native iOS application to allow your users to authenticate using Sign In with Apple. For more implementation details, you can try the Auth0 [iOS Swift - Sign In with Apple Quickstart](/quickstart/native/ios-swift-siwa).
+
+## How it works
+
+For a native app, the Sign in with Apple login flow works as follows:
+
+
+
+* **Steps 1 & 2**: User authenticates via Apple's SDK on their iOS device, and receive an authorization code in the response. The user does not have to leave the app and use a browser to log in.
+ ::: warning
+ Avoid using a nonce. It will cause the request to Apple to fail in step 4 and Auth0 will return a 400 error to the user: "Error from Apple connection."
+ :::
+* **Step 3**: The application calls Auth0's `/oauth/token` endpoint to exchange the Apple authorization code for Auth0 tokens.
+* **Step 4 & 5**: The Auth0 platform exchanges the Authorization code with Apple for tokens. Auth0 validates the tokens, and uses the claims in the tokens to construct the identity of the user.
+* **Step 6**: Auth0 saves the user profile, executes rules and authorization, then issues Auth0 access tokens (refresh tokens and ID tokens) as requested. These tokens are used to protect your APIs and users managed by Auth0.
+
+## Prerequisites
+
+Before you configure Sign In with Apple for your native app in Auth0, you must:
+
+* Have an [Apple Developer](https://developer.apple.com/programs/) account, which is a paid account with Apple. (There is no free trial available unless you are part of their [iOS Developer University Program](https://developer.apple.com/support/compare-memberships/).)
+* [Register Your App in the Apple Developer Portal](/connections/apple-siwa/set-up-apple) if you have not already done so. Make a note of the following IDs and key for the application connection settings in the Auth0 Dashboard:
+ * App ID
+ * Apple Team ID
+ * Client Secret Signing Key
+ * Key ID
+
+::: note
+If you are using the Classic Universal Login flow or embedding `Lock.js` in your application, make sure you are using `Lock.js` version 11.16 or later.
+:::
+
+## Configure and enable the connection in Auth0
+
+Once you have the credentials you need from your Apple Developer account, you need to configure the application client and the connection settings in Auth0.
+
+1. Navigate to [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications), choose your application, and select the gear icon to view the settings page.
+1. At the bottom of the page, select **Show Advanced Settings** and then the **Device Settings** view. Under **Native Social Login**, enable the **Enable Sign In with Apple** toggle.
+ 
+1. Under **iOS**, fill in the **App ID** field with the native app's App ID/Bundle Identifier.
+1. Navigate to [Auth0 Dashboard > Authentication > Social](${manage_url}/#/connections/social), and select **Create Connection**.
+1. Select the **Apple** connection and consent.
+1. On the **Settings** tab, fill in the following fields:
+ * **Apple Team ID**
+ * **Client Secret Signing Key**
+ * **Key ID**
+
+ 
+1. Select the **Applications** view to enable this connection for your application
+1. Click **Save**.
+
+::: note
+Native apps cannot be tested from the browser. This means that the **Try Connection** button on the Apple connection is used exclusively for testing web-based flows.
+:::
+
+## Logout
+
+Since the Native iOS login implementation does not make use of standard browser-based flows, application owners must also take care to perform logout appropriately. When an application needs to perform a logout, it must take the following actions:
+
+ * [Revoke the Auth0 Refresh Token](/api/authentication#revoke-refresh-token)
+ * Delete the Auth0 refresh token stored in the iCloud Keychain
+ * Delete the Apple user identifier stored in the iCloud keychain
+
+Also, keep in mind that logout can result from user actions (i.e., clicking a "log out" button) or from a user revoking access to the given app. The latter will be indicated through the native [ASAuthorizationAppleIDProvider.getCredentialState](https://developer.apple.com/documentation/authenticationservices/asauthorizationappleidprovider/3175423-getcredentialstate) method.
+
+:::note
+One nuance of Apple's IdP is that it only returns requested scopes (such as email, first name, and last name) in the ID token on the **first** response. More destructive approaches to logout (such as deleting the user) could result in loss of profile information, which would require end users to unauthorize and reauthorize an app.
+:::
+
+## Keep reading
+
+* [Rate Limits on Native Social Logins](/policies/rate-limits#limits-on-native-social-logins)
+* [Test Sign In with Apple Configuration](/connections/apple-siwa/test-siwa-connection)
diff --git a/articles/connections/social/apple.md b/articles/connections/social/apple.md
new file mode 100644
index 0000000000..0f807aeb82
--- /dev/null
+++ b/articles/connections/social/apple.md
@@ -0,0 +1,27 @@
+---
+title: Connect Web Apps to Apple
+connection: Apple
+image: /media/connections/apple.png
+seo_alias: apple
+description: Learn how to add login functionality to your web app with Apple. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+toc: true
+public: true
+index: 2
+topics:
+ - authentication
+ - connections
+ - social
+ - apple
+contentType: concept
+useCase:
+ - add-login
+ - connections
+ - add-siwa
+---
+<%= include('../../../snippets/social/apple/0') %>
+<%= include('../../../snippets/social/apple/1') %>
+<%= include('../../../snippets/social/apple/2') %>
+<%= include('../../../snippets/social/apple/3') %>
+<%= include('../../../snippets/social/apple/4') %>
+<%= include('../../../snippets/social/apple/5') %>
+<%= include('../../../snippets/social/apple/6') %>
diff --git a/articles/connections/social/auth0-oidc.md b/articles/connections/social/auth0-oidc.md
index 5ffaa85639..303c56f4e7 100644
--- a/articles/connections/social/auth0-oidc.md
+++ b/articles/connections/social/auth0-oidc.md
@@ -1,124 +1,18 @@
---
connection: Auth0 OpenIDConnect
-seo_alias: auth0-oidc
+title: Auth0 OpenIDConnect Connection
image: /media/connections/auth0.png
+public: false
description: You can use an Application on another Auth0 tenant as an OIDC identity provider in your current Auth0 tenant.
-toc: true
+topics:
+ - connections
+ - social
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Authenticate using OpenIDConnect to another Auth0 Tenant
-
-You can use application on another Auth0 tenant (referred to below as the **OIDC Provider tenant**) as an identity provider in your current Auth0 tenant (the **Relying Party tenant**).
-
-## Configure the OIDC Provider Auth0 Tenant
-
-1. Create an Application or edit an existing one. Set the application type to regular web app.
-2. Take note of its **Client ID** and **Client Secret**. You will need these to create the connection in the Relying Party tenant.
-3. Add the Relying Party tenant's login callback to the list of **Allowed Callback URLs**: `https://${account.namespace}/login/callback`
-
-
-
-4. Ensure that the **OIDC-Conformant** toggle in the **OAuth** tab under the application's **Advance Settings** is turned **off**.
-
-::: note
-The requirement for the **OIDC-Conformant** toggle to be **off** is a temporary requirement that will be removed in the future.
-:::
-
-## Configure the Relying Party Auth0 Tenant
-
-The Auth0-to-Auth0 connection is not yet supported in the Dashboard. You need to create the connection using the [Create a connection](/api/v2#!/Connections/post_connections) endpoint, which will require an [Management API V2 token](/api/management/v2/tokens) with `create:connections` scope.
-
-Here is a sample request:
-
-```sh
-curl -H "Content-Type: application/json" -H 'Authorization: Bearer {YOUR_API_V2_TOKEN}' -d @auth0-oidc-connection.json https://${account.namespace}/api/v2/connections
-```
-
-with the **auth0-oidc-connection.json** file containing:
-
-```js
-{
- "name": "YOUR-AUTH0-CONNECTION-NAME",
- "strategy": "auth0-oidc",
- "options": {
- "client_id": "OIDC_PROVIDER_CLIENT_ID",
- "client_secret": "OIDC_PROVIDER_CLIENT_SECRET",
- "domain": "OIDC_PROVIDER_AUTH0_DOMAIN",
- "scope": "openid"
- },
- "enabled_clients":["${account.clientId}"]
-}
-```
-
-The required parameters for this connection are:
-
-* **name**: how the connection will be referenced in Auth0 or in your app.
-* **strategy**: defines the protocol implemented by the provider. This should always be `auth0-oidc`.
-* **options.client_id**: the `clientID` of the target Application in the OIDC Provider Auth0 tenant.
-* **options.client_secret**: the `cliendSecret` of the target Application in the OIDC Provider Auth0 tenant.
-* **options.domain**: the domain of the OIDC Provider Auth0 tenant.
-
-Optionally, you can add:
-
-* **options.scope**: the scope parameters for which you wish to request consent (such as `profile`, `identities`, and so on).
-* **enabled_clients**: an array containing the identifiers of the applications for which the connection is to be enabled. If the array is empty or the property is not specified, no applications are enabled.
-
-## Use the Auth0 connection
-
-You can use any of the standard Auth0 mechanisms (such as direct links, [Auth0 Lock](/libraries/lock), [auth0.js](/auth0js), and so on) to login a user with the auth0-oidc connection.
-
-A direct link would look like:
-
-```text
-https://${account.namespace}/authorize/?client_id=${account.clientId}&response_type=code&redirect_uri=${account.callback}&state=OPAQUE_VALUE&connection=YOUR-AUTH0-CONNECTION-NAME
-```
-
-To add a custom connection in Lock, you can add a custom button as described in [Adding a new UI element using JavaScript](/libraries/lock/v9/ui-customization#adding-a-new-ui-element-using-javascript) and use the direct link as the button `href`.
-
-The user will be redirected to the built-in login page of the OIDC Provider Auth0 tenant where they can choose their identity provider (from the enabled connections of the target Application) and enter their credentials.
-
-
-
-## The resulting profile
-
-Once the user is authenticated, the resulting profile will contain the [Auth0 Normalized User Profile](/user-profile/normalized) fields. For example:
-
-```js
-{
- "name": "user-in-child@mail.com",
- "email": "user-in-child@mail.com",
- "email_verified": false,
- "nickname": "user-in-child",
- "picture": "https://s.gravatar.com/avatar/cb89d47afd405d39a8bce96b8b17bcbc?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fus.png",
- "clientID": "${account.clientId}",
- "updated_at": "2015-11-05T18:10:17.813Z",
- "user_id": "auth0-oidc|your-auth0-oidc-conn-name|auth0|563b9b6cf50bc24402a69b80",
- "identities": [
- {
- "user_id": "your-auth0-oidc-conn-name|auth0|563b9b6cf50bc24402a69b80",
- "provider": "auth0-oidc",
- "connection": "tenant2",
- "isSocial": true
- }
- ],
- "created_at": "2015-11-05T18:09:49.575Z",
- "global_client_id": "abOXA94rTYTYk6wDZsbQXJBv5VYiArmI",
- "persistent": {}
-}
-```
-
-Note that the generated `user_id` has the following format:
-
-`auth0-oidc|YOUR_AUTH0_CONNECTION_NAME|THE_OIDC_PROVIDER_AUTH0_CONNECTION|THE_OIDC_PROVIDER_USER_ID`
-
-The `access_token` is the JWT of the user in the OIDC Provider Auth0 connection. If you decode it, you will see all the properties that were requested in the `scope` of the auth0-oidc connection. For example, for `scope=openid email` will return:
-
-```js
-{
- "email": "john.doe@domain.com",
- "iss": "https://oidc-provider.auth0.com/",
- "sub": "auth0|563b9b6cf50bc24402a69b80",
- "aud": "eQVR4UI4b6ht1hXIcb90cMJN6pvvDPWD",
- "exp": 1446783017,
- "iat": 1446747017
-}
-```
+<%= include('../../../snippets/social/auth0-oidc/0') %>
+<%= include('../../../snippets/social/auth0-oidc/1') %>
+<%= include('../../../snippets/social/auth0-oidc/2') %>
+<%= include('../../../snippets/social/auth0-oidc/3') %>
diff --git a/articles/connections/social/baidu.md b/articles/connections/social/baidu.md
index bb768547f4..afdfb9ba85 100644
--- a/articles/connections/social/baidu.md
+++ b/articles/connections/social/baidu.md
@@ -1,36 +1,25 @@
---
-title: Connect your app to Baidu
+title: Connect Apps to Baidu
connection: Baidu
image: /media/connections/baidu.png
seo_alias: baidu
-description: How to obtain an API Key and Secret Key for Baidu.
+description: Learn how to add login functionality to your app with Baidy. You will need to obtain a Client Id and Client Secret for Baidu.
toc: true
+public: true
+index: 3
+topics:
+ - connections
+ - social
+ - baidu
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Baidu
-
-To configure a Baidu OAuth2 connection, you will need to register your Auth0 tenant on their [integration portal](https://developer.baidu.com/dev).
-
-## 1. Log into the integration portal and register a new App:
-
-
-
-
-## 2. Get your API Key and Secret Key
-
-Once the application is registered, enter your new `API Key` and `Secret Key` into the connection settings in Auth0.
-
-
-
-
-## 3. Enter the callback URL:
-
-Use the following value for the callback URL:
-
- https://${account.namespace}/login/callback
-
-Select your application on the console, and then click on `API 管理 -> 安全设置`
-
-
-
+<%= include('../../../snippets/social/baidu/0') %>
+<%= include('../../../snippets/social/baidu/1') %>
+<%= include('../../../snippets/social/baidu/2') %>
+<%= include('../../../snippets/social/baidu/3') %>
+<%= include('../../../snippets/social/baidu/4') %>
+<%= include('../../../snippets/social/baidu/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/basecamp.md b/articles/connections/social/basecamp.md
new file mode 100644
index 0000000000..d397de664a
--- /dev/null
+++ b/articles/connections/social/basecamp.md
@@ -0,0 +1,30 @@
+---
+title: Connect Apps to Basecamp
+connection: Basecamp
+image: /media/connections/basecamp.png
+alias:
+ - basecamp
+ - thirtysevensignals
+seo_alias: 37signals
+description: How to obtain a Client Id and Client Secret for Basecamp (formerly 37Signals).
+toc: true
+public: true
+index: 4
+topics:
+ - connections
+ - social
+ - 37signals
+ - basecamp
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+ - add-login
+---
+<%= include('../../../snippets/social/basecamp/0') %>
+<%= include('../../../snippets/social/basecamp/1') %>
+<%= include('../../../snippets/social/basecamp/2') %>
+<%= include('../../../snippets/social/basecamp/3') %>
+<%= include('../../../snippets/social/basecamp/4') %>
+<%= include('../../../snippets/social/basecamp/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/bitbucket.md b/articles/connections/social/bitbucket.md
index 712c311e8f..d5a6229b6b 100644
--- a/articles/connections/social/bitbucket.md
+++ b/articles/connections/social/bitbucket.md
@@ -1,91 +1,25 @@
---
-title: Connect your app to Bitbucket
connection: Bitbucket
+title: Bitbucket Social Connection
image: /media/connections/bitbucket.png
seo_alias: bitbucket
-description: This page shows you how to connect your Auth0 app to Bitbucket. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+description: Learn how to connect your Auth0 app to Bitbucket. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
toc: true
+public: true
+index: 5
+topics:
+ - connections
+ - social
+ - bitbucket
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Connect your app to Bitbucket
-
-To connect your Auth0 app to Bitbucket, you will need to generate a *Key* and *Secret* in a Bitbucket app, copy these keys into your Auth0 settings, and enable the connection.
-
-::: note
- This connection will only work with Lock version 9.2 or higher.
-:::
-
-## 1. Login to Bitbucket
-
-Login to [Bitbucket](https://bitbucket.org/).
-
-Click on your account icon in the upper right and select **Bitbucket settings**:
-
-
-
-Select **OAuth** in the left nav:
-
-
-
-## 2. Create your app
-
-Click **Add consumer**.
-
-Provide a name for your app.
-
-In the Callback URL field, enter the folowing:
-
-`https://${account.namespace}/login/callback`
-
-Select the Permissions you want to enable for this connection. At the very least you will need to select the `Account:Email` and `Account:Read` permissions.
-
-Click **Save**.
-
-
-
-## 3. Get your *Key* and *Secret*
-
-On the page that follows, click the name of your app under **OAuth consumers** to reveal your keys:
-
-
-
-## 4. Copy your *Client Id* and *Client Secret* into Auth0
-
-In a separate window, login to your [Auth0 Dashboard](${manage_url}) and select **Connections > Social** in the left nav.
-
-Select **Bitbucket**:
-
-
-
-Copy the `Key` and `Secret` from the **OAuth integrated applications** page on Bitbucket into the fields on this page on Auth0.
-
-Select the **Permissions** you want to enable.
-
-Click **SAVE**.
-
-
-
-## 5. Enable the Connection
-
-Go to the **Apps** tab of the Bitbucket connection on Auth0 and select each of your existing Auth0 apps for which you want to enable this connection:
-
-
-
-## 6. Test the connection
-
-Close the **Settings** window to return to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-A **TRY** icon will now be displayed next to the Bitbucket logo:
-
-
-
-Click **TRY**.
-
-Click **Grant access** to allow your app access.
-
-
-
-If you have configured everything correctly, you will see the **It works!!!** page:
-
-
-
+<%= include('../../../snippets/social/bitbucket/0') %>
+<%= include('../../../snippets/social/bitbucket/1') %>
+<%= include('../../../snippets/social/bitbucket/2') %>
+<%= include('../../../snippets/social/bitbucket/3') %>
+<%= include('../../../snippets/social/bitbucket/4') %>
+<%= include('../../../snippets/social/bitbucket/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/box.md b/articles/connections/social/box.md
index 19f0558aaf..f37f77a117 100644
--- a/articles/connections/social/box.md
+++ b/articles/connections/social/box.md
@@ -1,47 +1,25 @@
---
-title: Connect your app to Box
+title: Connect Apps to Box
connection: Box
image: /media/connections/box.png
seo_alias: box
-description: How to obtain a Client Id and Client Secret for Box.
+description: Learn how to add login functionality to your app with Box. You will need to obtain a Client Id and Client Secret for Box.
toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - box
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Box
-
-To configure a Box OAuth2 connection, you will need to register your Auth0 tenant on their [developer portal](https://developers.box.com/).
-
-## 1. Register a new Box app
-
-Log into the Box developer portal and click **My Apps** and then select **Create a Box Application**:
-
-
-
-Name your new app and click **Create Application**:
-
-
-
-## 2. Edit your app Properties
-
-Once the app is created, click on **Edit Application** and review the form. There are a number of properties that you can change (such as contact information, logos, and so on):
-
-
-
-Scroll down to find the `client_id` and `client_secret` fields under the **OAuth2 Parameters** section:
-
-
-
-Enter this URL as the `redirect_uri`:
-
- https://${account.namespace}/login/callback
-
-While on this page, make sure to define the appropriate permission **Scopes** for your app.
-
-## 3. Copy your *Client Id* and *Client Secret*
-
-Go to your Auth0 Dashboard and select **Connections > Social**, then choose **Box**. Copy the `Client Id` and `Client Secret` from the **OAuth2 Parameters** section of your app on Box into the fields on this page on Auth0:
-
-
-
+<%= include('../../../snippets/social/box/0') %>
+<%= include('../../../snippets/social/box/1') %>
+<%= include('../../../snippets/social/box/2') %>
+<%= include('../../../snippets/social/box/3') %>
+<%= include('../../../snippets/social/box/4') %>
+<%= include('../../../snippets/social/box/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/clever.md b/articles/connections/social/clever.md
new file mode 100644
index 0000000000..0f076fb330
--- /dev/null
+++ b/articles/connections/social/clever.md
@@ -0,0 +1,20 @@
+---
+title: Connect Apps to Clever
+connection: Clever
+image: /media/connections/clever.png
+seo_alias: clever
+description: For security reasons, Auth0 no longer integrates with Clever.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - clever
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/clever/0') %>
+
diff --git a/articles/connections/social/devkeys.md b/articles/connections/social/devkeys.md
index e3d3f78928..67f8dfc5cf 100644
--- a/articles/connections/social/devkeys.md
+++ b/articles/connections/social/devkeys.md
@@ -1,17 +1,27 @@
---
description: Caveats you need to be aware of when using Auth0 Dev Keys for social providers.
+topics:
+ - connections
+ - social
+ - dev-keys
+contentType: reference
+useCase:
+ - customize-connections
+ - add-idp
---
# Test Social Connections with Auth0 Developer Keys
-When using any of the available [Social Identity Providers](/identityproviders#social), you need to register your application with the relevant Identity Provider in order to obtain a Client ID and Client Secret.
+When using any of the available [Social Identity Providers](/connections/identity-providers-social), you need to register your application with the relevant Identity Provider in order to obtain a Client ID and Client Secret.
-Auth0 allows you to test a Social Identity Provider without specifying your own Client ID and Client Secret by using Auth0 developer keys. This allows you to quickly enable and test a specific Social Identity Provider, but it should **not be used in production**.
+Auth0 allows you to test a Social Identity Provider without specifying your own Client ID and Client Secret by using Auth0 developer keys. This allows you to quickly enable and test a specific Social Identity Provider, but it should **not be used in production**.
+
+Auth0 developer keys are not available in [Private Cloud deployments](/private-cloud).
For production environments, make sure to [follow the steps for your chosen provider](/identityproviders) to obtain the Client ID and Client secret from the provider, this will avoid the [limitations](#limitations-of-developer-keys) of using developer keys.
::: panel-warning Custom Developer keys
-One or more connections are using Auth0 development keys which are only intended for use in development and testing. The connections should be configured with your own Developer Keys to enable the consent page to show your logo instead of Auth0's and to enable SSO for these connections. Auth0 development keys are not recommended for Production environments.
+One or more connections are using Auth0 development keys which are only intended for use in development and testing. The connections should be configured with your own Developer Keys to enable the consent page to show your logo instead of Auth0's and to configure Single Sign-on (SSO) for these connections. Auth0 development keys are not recommended for Production environments.
:::
::: panel Client ID and Client Secret
@@ -20,17 +30,21 @@ The exact terminology of a Client ID / Client Secret may differ between various
## Limitations of Developer Keys
-They Auth0 developer keys are to be used for testing purposes so there are a few caveats you need to be aware of when using them. These may cause your application to behave differently - or some functionality to not work at all - depending on whether you use your own Client ID and Client Secret, or whether you use the Auth0 developer keys.
+The Auth0 developer keys are to be used for testing purposes so there are a few caveats you need to be aware of when using them. These may cause your application to behave differently - or some functionality to not work at all - depending on whether you use your own Client ID and Client Secret, or whether you use the Auth0 developer keys.
-1. You cannot use developer keys with [custom domains](/custom-domains).
+When using the Auth0 developer keys, the authentication flow for the various Identity Providers will at times display Auth0's name, logo and information to your users. When you register your own application, you have the opportunity to use your own logo and other application information instead.
+
+
-1. When using the Auth0 developer keys, the consent screen for the various Identity Providers will display Auth0's logo and information to your users. When you register your own application you have the opportunity to use your own logo and other application information.
+## Limitations of Developer Keys when using Classic Universal Login
- 
+If you are using the [Classic Universal Login experience](/universal-login/classic), these limitations also apply:
-2. [Single Sign On](/sso) will not function properly when using the Auth0 developer keys. The reason for this is that the Auth0 developer applications with all the relevant Identity Providers are configured to call back to the URL `https://login.auth0.com/login/callback` instead of the callback URL for your own tenant, for example `https://${account.namespace}/login/callback`.
+1. You cannot use developer keys with [custom domains](/custom-domains).
+
+2. [Single Sign-on](/sso) will not function properly when using the Auth0 developer keys. The reason for this is that the Auth0 developer applications with all the relevant Identity Providers are configured to call back to the URL `https://login.auth0.com/login/callback` instead of the callback URL for your own tenant, for example `https://${account.namespace}/login/callback`.
- This results in the SSO cookie not being set on your own tenant domain, so the next time a user authenticates no SSO cookie will be detected, even if you configured your application to **Use Auth0 instead of the Identity Provider to do Single Sign On**.
+ This results in the SSO cookie not being set on your own tenant domain, so the next time a user authenticates no SSO cookie will be detected, even if you configured your application to **Use Auth0 instead of the Identity Provider to do Single Sign-on** (legacy tenants only).
3. [Redirecting users from Rules](/rules/redirect) will not function properly. This is because redirect rules are resumed on the endpoint `https://${account.namespace}/continue`. When using Auth0's developer keys, the session is established on a special endpoint that is generic and tenant agnostic, and calling `/continue` will not find your previous session, resulting in an error.
@@ -38,4 +52,6 @@ They Auth0 developer keys are to be used for testing purposes so there are a few
5. `prompt=none` won't work on the [/authorize](/api/authentication/reference#social) endpoint. [Auth0.js' checkSession() method](/libraries/auth0js#using-checksession-to-acquire-new-tokens) uses `prompt=none` internally, so that won't work either.
-6. If Auth0 is acting as a SAML Identity Provider and you use a social connection with the Auth0 developer keys, the generated SAML response will have some errors, like a missing `InResponseTo` attribute or an empty `AudienceRestriction` element.
+6. If Auth0 is acting as a SAML Identity Provider and you use a social connection with the Auth0 developer keys, the generated SAML response will have some errors, like a missing `InResponseTo` attribute or an empty `AudienceRestriction` element.
+
+7. [Multi-factor Authentication in Auth0](/mfa) will not function properly. When MFA authentication is successful, a post will generate in `https://${account.namespace}/mf`. When using Auth0's developer keys, the session is established on a special endpoint that is generic and tenant agnostic, and calling `/mf` will not find your previous session, resulting in an error
diff --git a/articles/connections/social/digitalocean.md b/articles/connections/social/digitalocean.md
new file mode 100644
index 0000000000..1291253272
--- /dev/null
+++ b/articles/connections/social/digitalocean.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to DigitalOcean
+connection: DigitalOcean
+image: /media/connections/digitalocean.png
+seo_alias: digitalocean
+description: Learn how to add login functionality to your app with DigitalOcean. You will need to obtain a Client ID and Client Secret for DigitalOcean.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - digitalocean
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/digitalocean/0') %>
+<%= include('../../../snippets/social/digitalocean/1') %>
+<%= include('../../../snippets/social/digitalocean/2') %>
+<%= include('../../../snippets/social/digitalocean/3') %>
+<%= include('../../../snippets/social/digitalocean/4') %>
+<%= include('../../../snippets/social/digitalocean/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/discord.md b/articles/connections/social/discord.md
new file mode 100644
index 0000000000..f72c9cac60
--- /dev/null
+++ b/articles/connections/social/discord.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Discord
+connection: Discord
+image: /media/connections/discord.png
+seo_alias: discord
+description: Learn how to add login functionality to your app with Discord. You will need to obtain a Client ID and Client Secret for Discord.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - discord
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/discord/0') %>
+<%= include('../../../snippets/social/discord/1') %>
+<%= include('../../../snippets/social/discord/2') %>
+<%= include('../../../snippets/social/discord/3') %>
+<%= include('../../../snippets/social/discord/4') %>
+<%= include('../../../snippets/social/discord/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/docomo.md b/articles/connections/social/docomo.md
index db0f9926d3..84d7c89092 100644
--- a/articles/connections/social/docomo.md
+++ b/articles/connections/social/docomo.md
@@ -1,69 +1,25 @@
---
-title: Connect your app to Docomo dAccount
+title: Connect Apps to Docomo dAccount
connection: Docomo
image: /media/connections/daccount.png
seo_alias: docomo
-description: How to obtain a Client ID and Client Secret for Docomo dAccount.
+description: Learn how to add login functionality to your app with Docomo dAccount. You will need to obtain a Client Id and Client Secret for Docomo.
toc: true
+public: true
+index: 7
+topics:
+ - connections
+ - social
+ - docomo
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Docomo dAccount
-
-To configure a Docomo dAccount connection you will need to register Auth0 on the [dAccount Connect Portal](https://dac-g.apl01.spmode.ne.jp/VIEW_OC01/GOCA00004/).
-
-## 1. Add a new Service
-
-First log in into your [dAccount Connect Portal](https://dac-g.apl01.spmode.ne.jp/VIEW_OC01/GOCA00004/), once you have logged in click on the **RP site information management (RPサイト情報管理画面)** link on the side navigation.
-
-
-
-This will bring up RP site information management page. Click the **Add new RP site info (新規RPサイト情報追加)** button to add a new service.
-
-
-
-Fill out the form by providing the following information:
-
-| Field | Description
---------|------------
-Service name (サービス名) | Your application's name.
-Service overview (サービス概要) | A brief description of your application.
-Access Token lifetime (アクセストークン有効期間 秒) | The lifetime of your Access Token in seconds.
-Redirect URI (リダイレクトURI) | The callback url for your application (`https://${account.namespace}/login/callback`)
-Available scopes (利用可能スコープ) | The scopes for the information you are requesting for your app.
-
-
-
-When finished, click **Register (登録)**.
-
-## 2. Get your **Client ID** and **Client Secret**
-
-Go to the details page for your service by clicking on the **Details (詳細)** button.
-
-
-
-This page will contain your **Client ID (クライアントID)** and **Client Secret (クライアントシークット)**, to be used in the next step.
-
-
-
-## 3. Setup the Connection to Auth0
-
-In a seperate tab or page, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-Click on the **NTT Docomo** connection.
-
-Enter your **Client ID** and **Client ID** from the dAccount Connect service you created, select your **Attributes** then click **SAVE**.
-
-
-
-Next on the **Clients** tab, enable which of your applications will be able to use this connection. After enabling the applications, click **SAVE**.
-
-## 4. Test the Connection
-
-On the [Connections > Social](${manage_url}/#/connections/social) page of the Auth0 dashboard you should now see a **TRY** button with the NTT Docomo connection.
-
-
-
-Click on this to test the new connection. If your connection has been correctly configured, this should take you to a login page where you can log in with your dAccount.
-
+<%= include('../../../snippets/social/docomo/0') %>
+<%= include('../../../snippets/social/docomo/1') %>
+<%= include('../../../snippets/social/docomo/2') %>
+<%= include('../../../snippets/social/docomo/3') %>
+<%= include('../../../snippets/social/docomo/4') %>
+<%= include('../../../snippets/social/docomo/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/dribbble.md b/articles/connections/social/dribbble.md
new file mode 100644
index 0000000000..a16be5240a
--- /dev/null
+++ b/articles/connections/social/dribbble.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Dribbble
+connection: Dribbble
+image: /media/connections/dribbble.png
+seo_alias: dribbble
+description: Learn how to add login functionality to your app with Dribbble. You will need to obtain a Client ID and Client Secret for Dribbble.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - dribbble
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/dribbble/0') %>
+<%= include('../../../snippets/social/dribbble/1') %>
+<%= include('../../../snippets/social/dribbble/2') %>
+<%= include('../../../snippets/social/dribbble/3') %>
+<%= include('../../../snippets/social/dribbble/4') %>
+<%= include('../../../snippets/social/dribbble/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/dropbox.md b/articles/connections/social/dropbox.md
index 289e2ebec3..5e5203dc45 100644
--- a/articles/connections/social/dropbox.md
+++ b/articles/connections/social/dropbox.md
@@ -1,90 +1,25 @@
---
-title: Connect your app to Dropbox
+title: Connect Apps to Dropbox
connection: Dropbox
image: /media/connections/dropbox.png
seo_alias: dropbox
-description: This page shows you how to connect your Auth0 app to Dropbox. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+description: Learn how to connect your Auth0 app to Dropbox. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
toc: true
+public: true
+index: 8
+topics:
+ - connections
+ - social
+ - dropbox
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Dropbox
-
-To connect your Auth0 app to Dropbox, you will need to generate a *Client ID* and *Client Secret* in a Dropbox app, copy these keys into your Auth0 settings, and enable the connection.
-
-::: note
- Heads up! This connection will only work with Lock version 9.2 or higher.
-:::
-
-## 1. Login to the developer portal
-
-Go to the [Dropbox Developer](https://www.dropbox.com/developers) portal and log in with your Dropbox credentials.
-
-Click **Create your app**:
-
-
-
-## 2. Create your app
-
-1. Under **Choose an API**, select **Dropbox API**.
-2. Under **Choose the type of access you need**, select **App folder** or **Full Dropbox**, depending on your needs.
-3. Name your app.
-4. Click **Create app**.
-
-
-
-## 3. Enter your callback URL
-
-On your app's **Settings** page that follows, enter this URL in the **Redirect URIs** field:
-
-`https://${account.namespace}/login/callback`
-
-Click **Add**:
-
-
-
-## 4. Get your *Client ID* and *Client Secret*
-
-On the same **Settings** page, your `App key` and `App secret` will be displayed:
-
-
-
-## 5. Copy your *Client Id* and *Client Secret* into Auth0
-
-In a separate window, login to your [Auth0 Dashboard](${manage_url}) and select **Connections > Social** in the left nav.
-
-Select **Dropbox**.
-
-
-
-Copy the `App key` and `App secret` from the **Settings** page of the Dropbox Developer portal into the fields on this page on Auth0:
-
-
-
-Click **SAVE**.
-
-## 6 Enable the Connection
-
-Select the **Apps** tab of the Dropbox connection on Auth0 and select each of your existing Auth0 apps for which you want to enable this connection:
-
-
-
-## 7 Test the connection
-
-Close the **Settings** window to return to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-A **TRY** icon will now be displayed next to the Dropbox logo:
-
-
-
-Click **TRY**.
-
-Click **Allow** to grant your app access.
-
-
-
-If you have configured everything correctly, you will see the **It works!!!** page:
-
-
-
+<%= include('../../../snippets/social/dropbox/0') %>
+<%= include('../../../snippets/social/dropbox/1') %>
+<%= include('../../../snippets/social/dropbox/2') %>
+<%= include('../../../snippets/social/dropbox/3') %>
+<%= include('../../../snippets/social/dropbox/4') %>
+<%= include('../../../snippets/social/dropbox/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/dwolla.md b/articles/connections/social/dwolla.md
index 63c26bf1b7..1a7aa00217 100644
--- a/articles/connections/social/dwolla.md
+++ b/articles/connections/social/dwolla.md
@@ -1,43 +1,25 @@
---
-title: Connect your app to Dwolla
+title: Connect Apps to Dwolla
connection: Dwolla
image: /media/connections/dwolla.png
seo_alias: dwolla
-description: How to obtain a Client Id and Client Secret for Dwolla.
+description: Learn how to add login functionality to your app with Dwolla. You will need to obtain a Client Id and Client Secret for Dwolla.
toc: true
+public: true
+index: 9
+topics:
+ - connections
+ - social
+ - dwolla
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Dwolla
-
-To configure OAuth2 connections with Dwolla, you will need to register Auth0 on the Dwolla Developer portal.
-
-## 1. Log into the developer portal
-
-Log into the Dwolla [Developer portal](https://uat.dwolla.com/applications) and click **Create an application**:
-
-
-
-## 2. Register your new app
-
-Complete the information on this page. Enter the following URL in the **OAuth Redirect URL** field:
-
- https://${account.namespace}/login/callback
-
-
-
-Click **Create application**.
-
-## 3. Get your *Key* and *Secret*
-
-Once the application is registered, your app's `Key` and `Secret` will be displayed on the following page:
-
-
-
-## 4. Copy your *Key* and *Secret*
-
-Go to the [Social Connections](${manage_url}/#/connections/social) section of your Auth0 Dashboard and choose **Dwolla**. Copy the `Key` and `Secret` from the **Application** page of your app on Dwolla into the `Client Id` and `Client Secret` fields on this page on Auth0:
-
-
-
+<%= include('../../../snippets/social/dwolla/0') %>
+<%= include('../../../snippets/social/dwolla/1') %>
+<%= include('../../../snippets/social/dwolla/2') %>
+<%= include('../../../snippets/social/dwolla/3') %>
+<%= include('../../../snippets/social/dwolla/4') %>
+<%= include('../../../snippets/social/dwolla/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/evernote-sandbox.md b/articles/connections/social/evernote-sandbox.md
new file mode 100644
index 0000000000..ef6c0b5c73
--- /dev/null
+++ b/articles/connections/social/evernote-sandbox.md
@@ -0,0 +1,27 @@
+---
+title: Connect Apps to Evernote Sandbox
+connection: Evernote Sandbox
+image: /media/connections/evernote.png
+seo_alias: evernote-sandbox
+description: Learn how to add login functionality to your app with Evernote Sandbox. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+toc: true
+public: true
+index: 11
+topics:
+ - connections
+ - social
+ - evernote
+ - sandbox
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+ - add-login
+---
+<%= include('../../../snippets/social/evernote-sandbox/0') %>
+<%= include('../../../snippets/social/evernote-sandbox/1') %>
+<%= include('../../../snippets/social/evernote-sandbox/2') %>
+<%= include('../../../snippets/social/evernote-sandbox/3') %>
+<%= include('../../../snippets/social/evernote-sandbox/4') %>
+<%= include('../../../snippets/social/evernote-sandbox/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/evernote.md b/articles/connections/social/evernote.md
index 0c1cc07924..6970f35238 100644
--- a/articles/connections/social/evernote.md
+++ b/articles/connections/social/evernote.md
@@ -1,57 +1,26 @@
---
-title: Connect your app to Evernote
+title: Connect Apps to Evernote
connection: Evernote
image: /media/connections/evernote.png
seo_alias: evernote
-description: How to obtain a Consumer Key and Consumer Secret for Evernote.
+description: Learn how to add login functionality to your app with Evernote. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
toc: true
+public: true
+index: 10
+topics:
+ - connections
+ - social
+ - evernote
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+ - add-login
---
-
-# Connect your app to Evernote
-
-To configure Evernote OAuth connections, you will need to create an API Key on the Evernote Developers portal.
-
-## 1. Log into the Developers portal
-
-Log into the [Evernote Developers](http://dev.evernote.com) portal and click **Get an API Key**:
-
-
-
-## 2. Request an API Key
-
-Complete the information on this page and click **Request Key**.
-
-
-
-## 3. Get your *Consumer Key* and *Consumer Secret*
-
-Your `Consumer Key` and `Consumer Secret` will be displayed on the following page:
-
-
-
-## 4. Copy your *Consumer Key* and *Consumer Secret*
-
-Go to the [Social Connections](${manage_url}/#/connections/social) section of your Auth0 Dashboard and choose **Evernote Sandbox**. Copy the `Consumer Key` and `Consumer Secret` from the Evernote API Key page into the fields on this page on Auth0:
-
-
-
-## 5. Move your key to production
-
-When ready to deploy your application, you must request your API key be activated on production.
-
-Go to [Support Resources for Evernote Developers](https://dev.evernote.com/support/) and click **Activate an API Key**:
-
-
-
-Complete the information on this page, including you *API Consumer Key*, and click **Submit**:
-
-
-
-## 6. Copy your *Consumer Key* and *Consumer Secret*
-
-Go to the [Social Connections](${manage_url}/#/connections/social) section of your Auth0 Dashboard and choose **Evernote**. Copy the `Consumer Key` and `Consumer Secret` from the Evernote API Key page into the fields on this page on Auth0:
-
-
-
+<%= include('../../../snippets/social/evernote/0') %>
+<%= include('../../../snippets/social/evernote/1') %>
+<%= include('../../../snippets/social/evernote/2') %>
+<%= include('../../../snippets/social/evernote/3') %>
+<%= include('../../../snippets/social/evernote/4') %>
+<%= include('../../../snippets/social/evernote/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/exact.md b/articles/connections/social/exact.md
index 87dd492e84..fe6dee81a7 100644
--- a/articles/connections/social/exact.md
+++ b/articles/connections/social/exact.md
@@ -1,56 +1,25 @@
---
-title: Connect your app to Exact
+title: Connect Apps to Exact
connection: Exact
image: /media/connections/exact.png
seo_alias: exact
-description: How to obtain a Client Id and Client Secret for Exact.
+description: Learn how to add login functionality to your app with Exact.
toc: true
+public: true
+index: 12
+topics:
+ - connections
+ - social
+ - exact
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Exact
-
-To configure an Exact OAuth2 connection, you will need to register your Auth0 tenant on the [Exact Online App Center](https://apps.exactonline.com/).
-
-## 1. Register a new app
-
-Log into the Exact Online App Center and click on **Manage Apps**:
-
-
-
-and then click **Add a new application**:
-
-
-
-## 2. Edit your App Properties.
-
-Enter your app name:
-
-
-
-In the `Redirect URI`field, enter this value:
-
- https://${account.namespace}/login/callback
-
-and click **Save**.
-
-## 3. Get your new app's *Client Id* and *Client Secret*
-
-On the following page, your new app will be listed. To retrieve the `Client Id` and `Client Secret`, click **Edit**:
-
-
-
-On this page, from the **Authorization** section, copy the `Client Id` and `Client Secret` provided.
-
-
-
-## 4. Copy the *Client Id* and *Client Secret* to the Auth0 dashbaord.
-
-Go to your Auth0 Dashboard and select **Connections > Social**, then choose **Exact**. Copy the `Client Id` and `Client Secret` from the **Manage App** page of your app in the Exact Online App Center into the fields on this page on Auth0.
-
-
-
-::: note
-You can register applications in multiple regions with Exact. By default Auth0 will use `https://start.exactonline.nl`, but this value can be overridden with the `Base URL` parameter.
-:::
-
+<%= include('../../../snippets/social/exact/0') %>
+<%= include('../../../snippets/social/exact/1') %>
+<%= include('../../../snippets/social/exact/2') %>
+<%= include('../../../snippets/social/exact/3') %>
+<%= include('../../../snippets/social/exact/4') %>
+<%= include('../../../snippets/social/exact/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/facebook-native.md b/articles/connections/social/facebook-native.md
new file mode 100644
index 0000000000..b74d186c6c
--- /dev/null
+++ b/articles/connections/social/facebook-native.md
@@ -0,0 +1,129 @@
+---
+title: Add Facebook Login to Native Apps
+connection: Facebook Native
+image: /media/connections/facebook.png
+public: true
+description: Learn how to add login functionality to your native app with Facebook.
+topics:
+ - authentication
+ - connections
+ - social
+ - facebook
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
+---
+# Add Facebook Login to Native Apps
+
+You can add functionality to your native application to allow your users to authenticate using Facebook natively, within the application. This does not require redirection via a web browser and will let mobile applications comply with [Facebook Developer Policy](https://developers.facebook.com/policy/) which requires that mobile applications use the Facebook SDK for [Android](https://developers.facebook.com/docs/android) or [iOS](https://developers.facebook.com/docs/ios) to authenticate.
+
+::: note
+When integrating with the Facebook SDKs, your applications will be sharing data with Facebook. Make sure you understand the data that is being shared and that you reflect it properly in your application's privacy policy. Auth0 has no control over what data will be shared with Facebook via the SDK.
+
+Check the [Facebook GDPR](https://www.facebook.com/business/m/one-sheeters/gdpr-developer-faqs) page for more information about data collected by the Facebook SDK and Facebook Login.
+:::
+
+## How it works
+
+The Native Facebook login flow works as follows:
+
+* **Step 1**: The application authenticates a user via the Facebook SDK and acquires an Access Token.
+* **Step 2**: The application uses that Access Token to request a special [Facebook Session Info Access Token](https://developers.facebook.com/docs/facebook-login/access-tokens/session-info-access-token).
+* **Step 3**: Use the Facebook SDK to retrieve the users's profile
+* **Step 4**: The application can then use the Facebook Session Info token to authenticate with Auth0.
+
+## Prerequisites
+
+Before you configure Native Facebook login for your native app via Auth0, you must:
+
+1. [Set up your application](/connections/social/facebook) with Facebook and as an Auth0 connection
+1. [Use the relevant Facebook SDK in your application](https://developers.facebook.com/docs/apis-and-sdks/)
+1. Navigate to [Auth0 Dashboard > Applications > Applications](${manage_url}/#/applications), and create an application with Auth0 (if you have not already).
+1. At the bottom of the settings page, select **Show Advanced Settings** and then the **Device Settings** view. Under **Native Social Login**, enable the **Enable Sign In with Facebook** toggle.
+ 
+1. Complete the following implementation details:
+
+## Implementation details
+
+As above, the process to authenticate a user profile using Native Facebook login is a four-step one, from your application's perspective:
+
+### Step 1
+
+The application authenticates a user via the Facebook SDK. It will obtain an Access Token from Facebook.
+
+### Step 2
+
+The application uses the Access Token to request a [Facebook Session Info Access Token](https://developers.facebook.com/docs/facebook-login/access-tokens/session-info-access-token).
+
+This request will look similar to the following:
+
+```
+GET https://graph.facebook.com/v5.0/oauth/access_token?
+grant_type=fb_attenuate_token&
+client_id=457704041391802&
+fb_exchange_token=
+```
+
+and the response:
+
+```json
+{
+ "access_token": "XAAGgR4b...1lHWNCpqrAhcpoAZDZD",
+ "token_type": "bearer",
+ "expires_in": 5183924
+}
+```
+
+### Step 3
+
+The application needs to retrieve the user profile from Facebook using the Facebook SDK, which will end in a request similar to the following:
+
+```
+GET https://graph.facebook.com/v5.0/?access_token=&fields=email,name
+```
+
+### Step 4
+
+The application can then use the session info Access Token and the Facebook user profile to authenticate with Auth0 by calling Auth0's `/oauth/token` endpoint using the Token Exchange flow with the `facebook-session-access-token` token type. If all goes well, Auth0 will return a normal response from the exchange, with the addition of the user profile. The user profile should be a JSON object, encoded as a string.
+
+```
+POST https://${account.namespace}/oauth/token
+
+grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange'
+subject_token_type: 'http://auth0.com/oauth/token-type/facebook-info-session-access-token'
+audience: 'your-api'
+scope: 'read:appointments openid profile email email_verified'
+subject_token: 'XAAGgR4b...1lHWNCpqrUHZAEtUuZAhcpoAZDZD'
+client_id: '${account.clientId}'
+user_profile: '{"email":"john@example.com", "name":"John Doe"}'
+```
+
+and the response from Auth0:
+
+```json
+{
+ "access_token": "eyJ0eXA..yXQaPLVXg",
+ "id_token": "eyJ0.tFE5HPipdOsA",
+ "scope": "openid profile email read:appointments",
+ "expires_in": 86400,
+ "token_type": "Bearer"
+}
+```
+
+## User Profile and Email Validation
+
+In the previous example, you had to retrieve the User Profile from Facebook and include it in the call to `/oauth/token`. This is because the Facebook Session Access Token cannot be used to directly retrieve the profile, and the Facebook Access Token cannot be sent directly to the server, due to [Apple's AppStore Review Guidelines](https://developer.apple.com/app-store/review/guidelines). Therefore, it must be retrieved in the client and sent to Auth0 in this fashion.
+
+Given that Auth0 can't guarantee that the user profile is the same that was returned by Facebook, it will set the `email_verified` field to `false`.
+
+## Logout
+
+Since the native login implementation does not make use of standard browser-based flows, application owners must also take care to perform logout appropriately. When an application needs to perform a logout, it should also [Revoke the Auth0 Refresh Token](/api/authentication#revoke-refresh-token).
+
+## Keep reading
+
+* [Native Facebook Login with iOS Swift](/quickstart/native/ios-swift-facebook-login)
+* [Native Facebook Login with Android](/quickstart/native/android-facebook-login)
+* [Rate Limits on Native Social Logins](/policies/rate-limits#limits-on-native-social-logins)
diff --git a/articles/connections/social/facebook.md b/articles/connections/social/facebook.md
index 55cdcb50e3..7bf0d1cb91 100644
--- a/articles/connections/social/facebook.md
+++ b/articles/connections/social/facebook.md
@@ -1,135 +1,29 @@
---
-title: Connect your app to Facebook
+title: Connect Apps to Facebook
connection: Facebook
-index: 2
+index: 13
image: /media/connections/facebook.png
seo_alias: facebook
-description: This article shows you how to connect your app to Facebook
+description: Learn how to add login functionality to your app with Facebook. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
toc: true
+public: true
+topics:
+ - authentication
+ - connections
+ - social
+ - facebook
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
-# Connect your app to Facebook
-
-This article describes how to add login with Facebook to your app. It also discusses how you can get an Access Token in order to access the Facebook API.
-
-First you need to connect your Auth0 application to Facebook. This is summarized in the following steps:
-
-- Setup a Facebook app
-- Get your Facebook **App ID** and **App Secret**
-- Copy these keys into your Auth0 settings
-- Enable the Facebook social connection in Auth0
-
-## 1. Login to Facebook Developers
-
-Go to [Facebook Developers](https://developers.facebook.com) and login with your account. Select **Add a New App** from the dropdown in the upper right:
-
-
-
-## 2. Name your application
-
-Provide a **Display Name** and **Contact Email**.
-
-
-
-Next you will need to complete the **Security Check**.
-
-## 3. Setup Facebook Login
-
-On the **Product Setup** page that follows, click **Set Up** under **Facebook Login**:
-
-
-
-Next choose the type of application, for this tutorial we have selected **Web**.
-
-The **Quickstart** for **Facebook Login** will appear. Under the **Facebook Login** menu on the left, click on **Settings** to open the **Application OAuth Settings** page:
-
-
-
-Enter the following URL in the **Valid OAuth redirect URIs** field:
-
-`https://${account.namespace}/login/callback`
-
-::: panel Find your Auth0 domain name
-If your Auth0 domain name is not shown above, login to [the dashboard](${manage_url}) to find your **Tenant Name** in the top right corner. Your Auth0 domain is this name (for example `exampleco-enterprises`) plus `.auth0.com`. So for this example the **Valid OAuth redirect URI** would be: `https://exampleco-enterprises.auth0.com/login/callback`.
-:::
-
-
-
-Click **Save Changes**.
-
-## 4. Make your App Public
-
-Next, click on **App Review** on the left navigation bar. Near the top of the page under **Make (Your App Name) App public?** click to move the slider to **Yes**.
-
-
-
-## 5. Get your App ID and App Secret
-
-Click **Settings** in the left nav. On this page you can retrieve your **App ID** and **App Secret**.
-
-
-
-Click **Show** to reveal the **App Secret** (you may be required to re-enter your Facebook password).
-
-In a seperate tab or window, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-Click on the box with the **Facebook** logo.
-
-This will bring up the Facebook connection settings.
-
-Copy the **App ID** and **App Secret** from the **Settings** of your app on Facebook:
-
-
-
-Select all the **Attributes** and **Permissions** you want to enable.
-
-::: note
-Your users will be able to choose which Attributes they wish to share, and by default this selection is only made when they first authorize the application. [Click here to learn more about handling declined permissions.](/connections/social/reprompt-permissions)
-:::
-
-Then click the **Applications** tab and select the applications you wish to enable this connection for.
-
-
-
-When finished click **Save**.
-
-## 6. Test the Connection
-
-In the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard a **TRY** icon will now be displayed next to the Facebook logo:
-
-
-
-Click **TRY**.
-
-The Facebook allow access dialog will appear.
-
-
-
-Click continue and if configured correctly, you will see the **It works!!!** page:
-
-
-
-## 7. Access Facebook API
-
-<%= include('../_call-api', {
- "idp": "Facebook"
-}) %>
-
-## Additional Info
-
-You can find additional information at Facebook docs: [Add Facebook Login to Your App or Website](https://developers.facebook.com/docs/facebook-login).
-
-### Create a Test App
-
-Facebook now allows you to test your application by creating a copy of it to use for testing purposes. If you create a test application it will have it's own separate **App ID** and **App Secret**. Auth0 only allows one Facebook connection to be configured per tenant. One option for testing is that create the connection to the test connection and then change the values when you are ready to connect to the production application.
-
-Another option is to create another Auth0 tenant used for testing purposes. A new tenant can be created in the [Dashboard](${manage_url}) by clicking on your tenant name in the top right corner and selecting **+ Create Tenant** from the dropdown. See the [Setting Up Multiple Environments](/dev-lifecycle/setting-up-env) for more information on multiple environments.
-
-### Deauthorize Callback URL
-
-On the **Facebook Login** Client OAuth Settings page, you can also set a Deauthorize Callback URL to be called when a user deauthorizes your app.
-
-### Facebook Re-Authentication
-
-To force Facebook to prompt the user to [re-authenticate](https://developers.facebook.com/docs/facebook-login/reauthentication), you can set the `prompt='login'` value in Lock's `auth.param` object.
-
+<%= include('../../../snippets/social/facebook/0') %>
+<%= include('../../../snippets/social/facebook/1') %>
+<%= include('../../../snippets/social/facebook/2') %>
+<%= include('../../../snippets/social/facebook/3') %>
+<%= include('../../../snippets/social/facebook/4') %>
+<%= include('../../../snippets/social/facebook/5') %>
+<%= include('../../../snippets/social/facebook/6') %>
+<%= include('../../../snippets/social/facebook/7') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/figma.md b/articles/connections/social/figma.md
new file mode 100644
index 0000000000..2e1647388c
--- /dev/null
+++ b/articles/connections/social/figma.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Figma
+connection: Figma
+image: /media/connections/figma.png
+seo_alias: figma
+description: Learn how to add login functionality to your app with Figma. You will need to obtain a Client ID and Client Secret for Figma.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - figma
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/figma/0') %>
+<%= include('../../../snippets/social/figma/1') %>
+<%= include('../../../snippets/social/figma/2') %>
+<%= include('../../../snippets/social/figma/3') %>
+<%= include('../../../snippets/social/figma/4') %>
+<%= include('../../../snippets/social/figma/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/fitbit.md b/articles/connections/social/fitbit.md
index d1d783c9be..0442465522 100644
--- a/articles/connections/social/fitbit.md
+++ b/articles/connections/social/fitbit.md
@@ -1,74 +1,25 @@
---
-title: Connect your app to Fitbit
+title: Connect Apps to Fitbit
connection: Fitbit
image: /media/connections/fitbit.png
seo_alias: fitbit
-index: 14
-description: How to obtain a Client Id and Client Secret for Fitbit.
toc: true
+public: true
+index: 14
+description: Learn how to add login functionality to your app with Fitbit. You will need to obtain a Client Id and Client Secret for Fitbit.
+topics:
+ - connections
+ - social
+ - fitbit
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Fitbit
-
-::: panel-warning Fitbit has ended support for OAuth 1.0
-New connections with Fitbit will use OAuth 2.0. Please see the following documentation on [Using OAuth 2.0](https://dev.fitbit.com/docs/oauth2/) with Fitbit.
-:::
-
-To configure a Fitbit OAuth 2.0 connection, you will need to register a new application in Fitbit.
-
-## 1. Register a New Fitbit App
-
-Log in to the [Fitbit's Developer site](https://dev.fitbit.com), then select **REGISTER AN APP**:
-
-
-
-## 2. Complete the _Register an application_ form
-
-
-
-- **Application Name**- what you want to call your application
-- **Description**- describe what your application will be used for
-- **Application Website**- the URL of your application
-- **Organization**- the name of the associated organization
-- **Organization Website**- the URL of the associated organization
-- **OAuth 2.0 Application Type**- select **Application**, applications (clients) authenticate using either the Authorization Code Grant Flow or the Implicit Grant Flow
-- **Callback URL**- this is the URL called after a request, in this field enter: `https://${account.namespace}/login/callback`
-- **Default Access Type**- the type of access granted to the application
-
-When finished, click **Register**.
-
-## 3. Copy Your New App's *Client ID* and *Client Secret*
-
-From the **Edit Application** page, copy the **Client ID** and **Client Secret**:
-
-
-
-## 4. Enter Your Client ID and Client Secret
-
-Go to your Auth0 Dashboard and select **Connections > Social**, then choose **Fitbit**. Copy the **Client ID** and **Client Secret** from the **Manage My Apps** page of your app on Fitbit into the fields on this page on Auth0:
-
-
-
-## 5. Enable the Connection
-
-Go to the **Apps** tab of the Fitbit connection on your Auth0 Dashboard and select each of your existing Auth0 applications for which you want to enable this connection:
-
-
-
-## 6. Test the Connection
-
-Close the Settings window to return to the Connections > Social section of your Auth0 dashboard. A **TRY** icon will now be displayed next to the Fitbit logo; click "TRY".
-
-
-
-This will bring you to the authorization page. Click the **Allow** button to grant access.
-
-
-
-If you have configured everything correctly, you will see the "It works" page!
-
-::: note
-Fitbit is a registered trademark and service mark of Fitbit, Inc. Auth0 is designed for use with the Fitbit platform. This product is not part of Fitbit, and Fitbit does not service or warrant the functionality of this product.
-:::
-
+<%= include('../../../snippets/social/fitbit/0') %>
+<%= include('../../../snippets/social/fitbit/1') %>
+<%= include('../../../snippets/social/fitbit/2') %>
+<%= include('../../../snippets/social/fitbit/3') %>
+<%= include('../../../snippets/social/fitbit/4') %>
+<%= include('../../../snippets/social/fitbit/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/github.md b/articles/connections/social/github.md
index e586ab8f34..4e61bb806c 100644
--- a/articles/connections/social/github.md
+++ b/articles/connections/social/github.md
@@ -1,60 +1,27 @@
---
-title: Connect your app to GitHub
+title: Connect Apps to GitHub
connection: Github
image: /media/connections/github.png
seo_alias: github
-index: 7
-description: How to add GitHub login to your app and access their API
toc: true
+public: true
+index: 16
+description: Learn how to add login functionality to your app with GitHub. You can also access the GitHub API.
+topics:
+ - connections
+ - social
+ - github
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Connect your app to GitHub
-
-To configure a GitHub connection, you will need to register Auth0 with GitHub.
-
-This doc refers to the steps to connect your application. If you are looking to manage authentication in your application, see [Next Steps](#next-steps) below.
-
-## 1. Add a new application
-
-To add a new application, log in to [GitHub](https://github.com/) and go to **OAuth applications** in your [developer settings](https://github.com/settings/developers). Next click [Register a new application](https://github.com/settings/applications/new).
-
-
-
-## 2. Register your new app
-
-On the [Register a new application](https://github.com/settings/applications/new) page fill out the form with the following information:
-
-| Field | Description |
-| - | - |
-| Application name | The name of your app |
-| Homepage URL | `https://${account.namespace}` |
-| Application description | The description of your app users will see (Optional) |
-| Authorization callback URL | `https://${account.namespace}/login/callback` |
-
-
-
-After completing the form click **Register application** to proceed.
-
-## 3. Get your GitHub app's Client ID and Client Secret
-
-Once the application is registered, your app's `Client ID` and `Client Secret` will be displayed on the following page:
-
-
-
-## 4. Copy your GitHub app's Client ID and Client Secret
-
-Go to your [Auth0 Dashboard](${manage_url}) and select **Connections > Social**, then choose **Github**. Copy the `Client ID` and `Client Secret` from the **Developer Applications** of your app on Github into the fields on this page on Auth0.
-
-
-
-## 5. Access GitHub API
-
-<%= include('../_call-api', {
- "idp": "GitHub"
-}) %>
-
-## Troubleshooting
-
-If you are receiving `Access Denied` when calling the GitHub API, you probably have not requested the correct permissions for the user during login. For information on how to fix that, refer to [Add scopes/permissions to call Identity Provider's APIs](/connections/adding-scopes-for-an-external-idp).
+<%= include('../../../snippets/social/github/0.md') %>
+<%= include('../../../snippets/social/github/1.md') %>
+<%= include('../../../snippets/social/github/2.md') %>
+<%= include('../../../snippets/social/github/3.md') %>
+<%= include('../../../snippets/social/github/4.md') %>
+<%= include('../../../snippets/social/github/5.md') %>
+<%= include('../../../snippets/social/github/6.md') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/goodreads.md b/articles/connections/social/goodreads.md
index 0430ebf57f..670c3e39f4 100644
--- a/articles/connections/social/goodreads.md
+++ b/articles/connections/social/goodreads.md
@@ -1,116 +1,25 @@
---
-title: Connect your app to Goodreads
+title: Connect Apps to Goodreads
connection: Goodreads
image: /media/connections/goodreads.png
seo_alias: goodreads
-description: How to obtain a Consumer Key and Consumer Secret for Goodreads.
+toc: true
+public: false
+index: 17
+description: Learn how to add login functionality to your app with Goodreads.
+topics:
+ - connections
+ - social
+ - goodreads
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Connect your app to Goodreads
-
-This doc refers to the steps required to configure a Goodreads social connection in your Auth0 [dashboard](${manage_url}). If you are looking to manage authentication in your application, see [Next Steps](#next-steps) below.
-
-To configure a Goodreads connection with Auth0, you will need to register your app on the Goodreads developers site.
-
-## 1. Apply for a developer key
-
-Log into the [Goodreads developer site](https://www.goodreads.com/api), and select *developer key*:
-
-
-
-## 2. Enter information about your app
-
-Complete the form then click **Apply for a Developer Key**. Enter this in the `Callback URL` field:
-
-```text
-https://${account.namespace}/login/callback
-```
-
-
-
-## 3. Get your Consumer Key and Consumer Secret
-
-Once the application is registered, the **Key** and **Secret** for your new app will be displayed on the following page:
-
-
-
-## 4. Create the Goodreads connection
-
-You will need to use [this endpoint of our Management API v2](/api/management/v2#!/Connections/post_connections) to create a custom `oauth1` connection for Goodreads.
-
-[Read our documentation on creating generic OAuth1 connections](/tutorials/adding-generic-oauth1-connection) for more information on the individual fields used in the sample payload to follow. For Goodreads, this is a sample payload to create the connection:
-
-```har
- {
- "method": "POST",
- "url": "https://${account.namespace}/api/v2/connections",
- "httpVersion": "HTTP/1.1",
- "headers": [
- {
- "name": "Authorization",
- "value": "Bearer YOUR_API_V2_TOKEN_HERE"
- }
- ],
- "postData": {
- "mimeType": "application/json",
- "text": "{\"name\": \"custom-goodreads\",\"strategy\": \"oauth1\",\"enabled_clients\": [\"YOUR_ENABLED_CLIENT_ID\"],\"options\": {\"client_id\": \"YOUR_GOODREADS_KEY\",\"client_secret\": \"YOUR_GOODREADS_SECRET\",\"requestTokenURL\": \"http://www.goodreads.com/oauth/request_token\",\"accessTokenURL\": \"http://www.goodreads.com/oauth/access_token\",\"userAuthorizationURL\": \"http://www.goodreads.com/oauth/authorize\",\"scripts\": {\"fetchUserProfile\": \"function(token, tokenSecret, ctx, cb) {var OAuth = new require(\\\"oauth\\\").OAuth; var parser = require('xml2json'); var oauth = new OAuth(ctx.requestTokenURL, ctx.accessTokenURL, ctx.client_id, ctx.client_secret, \\\"1.0\\\", null, \\\"HMAC-SHA1\\\"); oauth.get(\\\"https://www.goodreads.com/api/auth_user\\\", token, tokenSecret, function(e, xml, r) { console.log(xml); if (e) return cb(e); if (r.statusCode !== 200) return cb(new Error(\\\"StatusCode: \\\" + r.statusCode)); try { var jsonResp = JSON.parse(parser.toJson(xml)); var user = jsonResp.GoodreadsResponse.user; cb(null, user); } catch (e) { console.log(e); cb(new UnauthorizedError(\\\"[+] fetchUserProfile: Goodreads fetch script failed. Check Webtask logs\\\")); } });}\"}}}"
- }
- }
- ```
-
-::: note
-You have to replace `YOUR_API_V2_TOKEN_HERE` with a Management API v2 token. You can [get one from the dashboard](${manage_url}/#/apis/management/explorer) or [follow this process](/api/management/v2/tokens#get-a-token-manually) if this is the first time.
-:::
-
-This sample uses the following `fetchUserProfile` script, you can change it as you please:
-
-```js
-function(token, tokenSecret, ctx, cb) {
- var OAuth = new require("oauth").OAuth;
- var parser = require('xml2json');
- var oauth = new OAuth(ctx.requestTokenURL, ctx.accessTokenURL, ctx.client_id, ctx.client_secret, "1.0", null, "HMAC-SHA1");
- oauth.get("https://www.goodreads.com/api/auth_user", token, tokenSecret, function(e, xml, r) {
- console.log(xml);
- if (e) return cb(e);
- if (r.statusCode !== 200) return cb(new Error("StatusCode: " + r.statusCode));
- try {
- var jsonResp = JSON.parse(parser.toJson(xml));
- var user = jsonResp.GoodreadsResponse.user;
- cb(null, user);
- }
- catch (e) {
- console.log(e);
- cb(new UnauthorizedError("[+] fetchUserProfile: Goodreads fetch script failed. Check Webtask logs"));
- }
- });
-}
-```
-
-
-::: panel-warning Goodreads returns limited user profile data
-If you have any [Rules](/rules) configured that rely on `user.email` for example, user authentication will likely fail - the sample Rule above currently only returns `user.id`, `user.name`, and `user.link` properties [from Goodreads' API](https://www.goodreads.com/api/index#auth.user). Please add appropriate error handling to any Rules or Hooks that may rely on other user-profile data that may be missing. You may use [our Real-time Webtask Logs extension](/extensions/realtime-webtask-logs) to help debug these sorts of issues further.
-:::
-
-If you do change the `fetchUserProfile` script, you can stringify the function easily for use in your `POST /api/v2/connections` payload as follows:
-
-```js
-JSON.stringify(`function(token, tokenSecret, ctx, cb) {
- // fetch user profile
-}`);
-```
-
-## 5. Test the connection
-
-You can use the [/authorize endpoint](/api/authentication?shell#authorize-application) with custom `client_id` and `connection` parameters to test your connection. For example:
-
-```text
-https://${account.namespace}/authorize?
- scope=YOUR_SCOPE&
- response_type=YOUR_RESPONSE_TYPE&
- client_id=YOUR_ENABLED_CLIENT_ID&
- redirect_uri=${account.callback}&
- connection=custom-goodreads&
- nonce=YOUR_CRYPTOGRAPHIC_NONCE
-```
-
-
+<%= include('../../../snippets/social/goodreads/0') %>
+<%= include('../../../snippets/social/goodreads/1') %>
+<%= include('../../../snippets/social/goodreads/2') %>
+<%= include('../../../snippets/social/goodreads/3') %>
+<%= include('../../../snippets/social/goodreads/4') %>
+<%= include('../../../snippets/social/goodreads/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/google.md b/articles/connections/social/google.md
index ada750c038..1ab56627fb 100644
--- a/articles/connections/social/google.md
+++ b/articles/connections/social/google.md
@@ -1,130 +1,31 @@
---
-title: Connect your app to Google
+title: Connect Apps to Google
connection: Google
-index: 1
+toc: true
+public: true
+index: 18
image: /media/connections/google.png
-description: This article describes how to connect your app to Google. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+description: Learn how to add login functionality to your app with Google. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
alias:
- gmail
- google-oauth
- google-oauth2
seo_alias: google
-toc: true
+topics:
+ - authentication
+ - connections
+ - social
+ - google
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
-# Connect your App to Google
-
-This article describes how to add login with Google functionality to your app. It also discusses how you can get an Access Token in order to access the Google API.
-
-First you need to connect your Auth0 application to Google. This is summarized in the following steps:
-
-1. Generate a **Client ID** and **Client Secret** in a Google project
-2. Enable the **Google Admin SDK Service**
-3. Copy your Google **Client ID** and **Client Secret** keys into your Auth0 dashboard
-4. Enable the Google social connection in Auth0
-
-::: warning
-If your client requests sensitive OAuth scopes, it may be [subject to review by Google](https://developers.google.com/apps-script/guides/client-verification).
-:::
-
-## 1. Generate the Google Client ID and Client Secret
-
-1. Log in to your Google account and go to the [APIs & services](https://console.developers.google.com/projectselector/apis/credentials).
-
-2. Navigate to **Credentials** using the left-hand menu:
-
- 
-
-3. On the **Credentials** page, click **Create credentials** and choose **OAuth client ID**.
-
- 
-
-4. On the **Create client id** page, select **Web application**. In the new fields that display, set the following parameters:
-
-| Field | Description |
-| - | - |
-| Name | The name of your web app |
-| Authorized JavaScript origins | `https://${account.namespace}` |
-| Authorized redirect URIs | `https://${account.namespace}/login/callback` |
-
- 
-
- Click **Create** to proceed.
-
-5. Your `Client Id` and `Client Secret` will be displayed:
-
- 
-
- Save your `Client Id` and `Client Secret` to enter into the Connection settings in Auth0.
-
-## 2. Enable the Admin SDK Service
-
-If you are planning to connect to Google Apps enterprise domains, you will need to enable the **Admin SDK** service.
-
-1. Navigate to the **Library** page of the API Manager.
-
-2. Select **Admin SDK** from the list of APIs:
-
- 
-
-3. On the **Admin SDK** page, click **Enable**. If successful, the **Enable** link turns into **Disable**.
-
- 
-
-## 3. Enable the Connection in Auth0
-
-1. Log in to the [Auth0 Dashboard](${manage_url}) and select **Connections > Social** in the left navigation.
-
-2. Select the connection with the Google logo to access this connection's **Settings** page:
-
- 
-
-3. Select each of your existing Auth0 Clients for which you want to enable this connection. Click **Save** when you're done.
-
- 
-
-4. Switch over to the *Settings* tab. Copy the `Client Id` and `Client Secret` from the Credentials page of your project in the **Google API Manager** into the fields on this page on Auth0.
-
- 
-
-5. Select the **Permissions** for each of the features you want to allow your app to access. Click **Save** when you're done.
-
-## 4. Test Your Connection
-
-1. Go back to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard. If you have configured your connection correctly, you will see a **Try** icon next to the Google logo:
-
- 
-
-2. Click **Try**.
-
-3. Click **Allow** in the permissions pop-up screen:
-
- 
-
-If you have configured everything correctly, you will see the **It works!!!** page:
-
- 
-
-## 5. Access Google API
-
-<%= include('../_call-api', {
- "idp": "Google"
-}) %>
-
-## Optional: Get a Refresh Token
-
-You can also get a [Refresh Token](/tokens/refresh-token) from Google in order to refresh your Access Token, once it expires.
-
-You can do this by setting the `access_type=offline` parameter when you call the [Auth0 `/authorize` endpoint](/api/authentication#social).
-
-If you use [Lock](/libraries/lock) you can set this parameter in the [params object](/libraries/lock/configuration#params-object-).
-
-Note that you can only get a Refresh Token, if you are using one of the following OAuth 2.0 flows:
-* [Authorization Code](/api-auth/grant/authorization-code)
-* [Authorization Code with PKCE](/api-auth/grant/authorization-code-pkce)
-* [Resource Owner Password](/api-auth/grant/password)
-
-:::note
-A Single Page Application (normally implementing the [Implicit Grant](/api-auth/grant/implicit)) should not under any circumstances get a Refresh Token. The reason for that is that the SPA is a public client and as such **cannot hold credentials securely**.
-:::
-
+<%= include('../../../snippets/social/google/0') %>
+<%= include('../../../snippets/social/google/1') %>
+<%= include('../../../snippets/social/google/2') %>
+<%= include('../../../snippets/social/google/3') %>
+<%= include('../../../snippets/social/google/4') %>
+<%= include('../../../snippets/social/google/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/imgur.md b/articles/connections/social/imgur.md
new file mode 100644
index 0000000000..aa6b7fdf15
--- /dev/null
+++ b/articles/connections/social/imgur.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Imgur
+connection: Imgur
+image: /media/connections/imgur.png
+seo_alias: imgur
+description: Learn how to add login functionality to your app with Imgur. You will need to obtain a Client ID and Client Secret for Imgur.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - imgur
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/imgur/0') %>
+<%= include('../../../snippets/social/imgur/1') %>
+<%= include('../../../snippets/social/imgur/2') %>
+<%= include('../../../snippets/social/imgur/3') %>
+<%= include('../../../snippets/social/imgur/4') %>
+<%= include('../../../snippets/social/imgur/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/index.md b/articles/connections/social/index.md
new file mode 100644
index 0000000000..de716ecff7
--- /dev/null
+++ b/articles/connections/social/index.md
@@ -0,0 +1,18 @@
+---
+title: Social Identity Providers
+description: Learn about the social identity providers supported by Auth0.
+topics:
+ - connections
+ - identity-providers
+contentType:
+ - reference
+useCase:
+ - customize-connections
+ - add-idp
+---
+# Social Identity Providers
+
+Auth0 supports the following social providers for web applications out of the box. You can also use any [OAuth2 Authorization Server](/connections/social/oauth2) or explore partner-supported social connections in the [Auth0 Marketplace](https://marketplace.auth0.com/).
+
+<% var socialConnections = cache.find('articles/connections/social', {sort: 'index'}); %>
+<%= include('../_connections', { connections: socialConnections }) %>
\ No newline at end of file
diff --git a/articles/connections/social/instagram.md b/articles/connections/social/instagram.md
index dae5289858..90dbc9e91a 100644
--- a/articles/connections/social/instagram.md
+++ b/articles/connections/social/instagram.md
@@ -1,115 +1,65 @@
---
-title: Connect your app to Instagram
+title: Connect Apps to Instagram
connection: Instagram
-index: 4
+index: 19
image: /media/connections/instagram.png
seo_alias: instagram
-description: This article shows you how to connect your Auth0 app to Instagram. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+description: Learn how to add login functionality to your app with Instagram. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
toc: true
+public: false
+topics:
+ - connections
+ - social
+ - instagram
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Connect your app to Instagram
+# Connect Apps to Instagram
-This article describes how to add login with Instagram to your app. It also discusses how you can get an Access Token in order to access the Instagram API.
+You can add functionality to your web app that allows your users to log in with Instagram.
-First you need to connect your Auth0 application to Instagram. This is summarized in the following steps:
-
-- Register a client at the Instagram Developer Portal
-- Get the **Client ID** and **Client Secret**
-- Copy these keys into your Auth0 settings
-- Enable the Instagram social connection in Auth0
-
-## 1. Log into the developer portal
-
-Go to the Instagram [Developer portal](http://instagram.com/developer) and log in with your Instagram credentials.
-
-If asked, complete the Developer Signup:
-
-
-
-On the page that follows, click **Register Your Application**:
-
-
-
-## 2. Register your app
-
-Click **Register a New Client**:
-
-
-
-## 3. Enter your callback URL
-
-Complete the form. Enter these values in the following fields:
-
-**Website URL**: `https://${account.namespace}`
-
-**Valid redirect URI**: `https://${account.namespace}/login/callback`
-
-Click **Register**.
-
-
-
-## 4. Get your Client ID and Client Secret
-
-Once your app is registered, you will be navigated to the **Manage Clients** page. Click on the **Manage** button for your new client.
-
-
-
-This will bring you to the page that contains your **Client ID** and **Client Secret**. Copy these for use in the next step.
-
-
-
-## 5. Copy your **Client Id** and **Client Secret** into Auth0
-
-In a separate window, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth Dashboard.
-
-Select **Instagram**.
-
-Copy the `Client Id` and `Client Secret` from the **Manage Client** page of the Instagram Developer portal into the fields on this page on Auth0.
-
-Select the **Permissions** you want to enable.
-
-Click **SAVE**.
-
-
-
-## 6. Enable the Connection
-
-Go to the **Apps** tab of the Instagram connection on Auth0 and select each of your existing Auth0 apps for which you want to enable this connection:
-
-
-
-## 7. Test the connection
+::: note
+Instagram has deprecated their legacy APIs in favor of the new [Instagram Graph API](https://developers.facebook.com/docs/instagram-basic-display-api), which requires users to authenticate using Facebook Login.
+:::
-Close the **Settings** window to return to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
+## Prerequisites
-A **TRY** icon will now be displayed next to the Instagram logo:
+Before you connect your Auth0 app to Instagram, you must have a [Facebook Developer](https://developers.facebook.com/) account. Follow the instructions in [Getting Started with the Instagram Graph API](https://developers.facebook.com/docs/instagram-api/getting-started/). You must get an access token that allows you to access the Facebook API.
-
+## Steps
-Click **TRY**.
+To connect your app to Instagram, you will:
-Click **Authorize** to allow your app access.
+1. [Set up your app with the Graph API](#set-up-your-app-with-the-graph-api)
+2. [Create and enable a connection in Auth0](#create-and-enable-a-connection-in-auth0)
+3. [Test the connection](#test-the-connection)
-
+### Set up your app with the Graph API
-If you have configured everything correctly, you will see the **It works!!!** page:
+1. Log in to the [Facebook Developer](https://developers.facebook.com/) portal.
+2. Follow steps for [App Development](https://developers.facebook.com/docs/apps#register) to register your app.
+3. Add **Facebook Login** to your app in the **App Dashboard**.
+4. On the **Facebook Login > Settings** page, under **Valid Oauth Redirect URIs**, enter your callback URL:
+ `https://${account.namespace}/login/callback`
-
+ You can also set a **Deauthorize Callback URL** that will be called when a user deauthorizes your app.
-[Click here to learn more about authentication with Instagram](https://www.instagram.com/developer/authentication/)
+<%= include('../_find-auth0-domain-redirects') %>
-## 8. Access Instagram API
+::: note
+If your application requests sensitive permissions, it may be [subject to review by Facebook](https://developers.facebook.com/docs/apps/review/). Only the `default` and `email` permissions do not currently require app review. For info on Facebook permissions, see Facebook's [Facebook Login Permissions Reference](https://developers.facebook.com/docs/facebook-login/permissions/).
+:::
-Once you successfully authenticate a user, Instagram includes an [Access Token](/tokens/access-token) in the user profile it returns to Auth0.
+Once you are done you should have two pieces of information: the **Client ID** and **Client Secret** for your app.
-You can then use this token to call their API.
+### Create and enable a connection in Auth0
-In order to get a Instagram Access Token, you have to retrieve the full user's profile, using the Auth0 Management API, and extrach the Access Token from the response. For detailed steps refer to [Call an Identity Provider API](/connections/calling-an-external-idp-api).
+[Set up the Instagram social connection](/dashboard/guides/connections/set-up-connections-social) in Auth0. Make sure you have the generated **Client ID** and **Client Secret**.
-Once you have the token you can call the API, following Instagram's documentation.
+### Test the connection
-::: note
-For more information on these tokens, refer to [Identity Provider Access Tokens](/tokens/idp).
-:::
+You're ready to [test your connection](/dashboard/guides/connections/test-connections-social). After logging in, you'll be prompted to allow your app access. To do so, click **Install unlisted app**.
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/line.md b/articles/connections/social/line.md
new file mode 100644
index 0000000000..6100242dc5
--- /dev/null
+++ b/articles/connections/social/line.md
@@ -0,0 +1,27 @@
+---
+title: Connect Apps to LINE
+connection: LINE
+toc: true
+public: true
+index: 20
+image: /media/connections/line.png
+seo_alias: line
+description: Learn how to add login functionality to your app with LINE. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - authentication
+ - connections
+ - social
+ - line
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/line/0') %>
+<%= include('../../../snippets/social/line/1') %>
+<%= include('../../../snippets/social/line/2') %>
+<%= include('../../../snippets/social/line/3') %>
+<%= include('../../../snippets/social/line/4') %>
+<%= include('../../../snippets/social/line/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/linkedin.md b/articles/connections/social/linkedin.md
index b45678a5d4..4420d9472c 100644
--- a/articles/connections/social/linkedin.md
+++ b/articles/connections/social/linkedin.md
@@ -1,95 +1,27 @@
---
-title: Connect Your App to LinkedIn
+title: Connect Apps to LinkedIn
connection: LinkedIn
-index: 3
+toc: true
+public: true
+index: 21
image: /media/connections/linkedin.png
seo_alias: linkedin
-description: This page shows you how to connect your Auth0 app to LinkedIn. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
-toc: true
+description: Learn how to add login functionality to your app with LinkedIn. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - authentication
+ - connections
+ - social
+ - linkedin
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
-
-# Connect Your App to LinkedIn
-
-To connect your Auth0 app to LinkedIn, you will need to generate a **Client ID** and **Client Secret** in a LinkedIn app, copy these keys into your Auth0 settings, and enable the connection.
-
-## 1. Log in to the developer portal
-
-Log in to the [LinkedIn Developer portal](http://developer.linkedin.com/), and click **My Apps**:
-
-
-
-## 2. Create your app
-
-Click the **Create Application** button:
-
-
-
-## 3. Enter details about your app
-
-For the **Website URL** field, enter the following URL:
-
-`https://${account.namespace}`
-
-Then complete all the required fields on the form.
-
-Click **Submit**.
-
-
-
-## 4. Enter the redirect URL
-
-Enter the following URL in the **Authorized Redirect URLs** field, and click **Add**:
-
-`https://${account.namespace}/login/callback`
-
-Next, click **Update**.
-
-
-
-## 5. Get your Client ID and Client Secret
-
-On the same page, you will be able to see your **Client ID** and **Client Secret** under the **Authentication Keys** section:
-
-
-
-## 6. Copy your Client ID and Client Secret into Auth0
-
-Login to the [Connections > Social section of the Auth0 Dashboard](${manage_url}/#/connections/social).
-
-Select the LinkedIn connection to access its **Settings** page.
-
-Copy the **Client ID** into the **API Key** section and **Client Secret** into the **Secret Key** section. Enable any desired permissions and attributes, then click **SAVE**.
-
-
-
-## 7. Enable the connection
-
-Go to the **Apps** tab of the LinkedIn connection on Auth0, and select each of your existing Auth0 apps for which you want to enable this connection:
-
-
-
-## 8. Test your app
-
-Go back to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-A **TRY** icon will now be displayed next to the LinkedIn logo:
-
-
-
-Click **TRY**.
-
-You will see the LinkedIn Authorize screen. Click **Allow** to finish creating the connection.
-
-
-
-If you have configured everything correctly, you will see the **It works!!!** page:
-
-
-
-## 9. Access LinkedIn API
-
-<%= include('../_call-api', {
- "idp": "LinkedIn"
-}) %>
-
+<%= include('../../../snippets/social/linkedin/0') %>
+<%= include('../../../snippets/social/linkedin/1') %>
+<%= include('../../../snippets/social/linkedin/2') %>
+<%= include('../../../snippets/social/linkedin/3') %>
+<%= include('../../../snippets/social/linkedin/4') %>
+<%= include('../../../snippets/social/linkedin/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/microsoft-account.md b/articles/connections/social/microsoft-account.md
index 70e01338ce..4ec2590a98 100644
--- a/articles/connections/social/microsoft-account.md
+++ b/articles/connections/social/microsoft-account.md
@@ -1,102 +1,32 @@
---
-title: Connect your app to Microsoft Account
+title: Connect Apps to Microsoft
connection: Microsoft Account
image: /media/connections/ms.png
-index: 12
+toc: true
+public: true
+index: 22
alias:
- live-id
- microsoft-live
- windowslive
- windows-live
seo_alias: microsoft-account
-description: How to configure your Auth0 app for an OAuth connection to Microsoft Account.
-toc: true
+description: Learn how to add login functionality to your app with Microsoft Accounts. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - authentication
+ - connections
+ - social
+ - microsoft
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Microsoft Account
-
-To connect your Auth0 app to Microsoft Account, you will need to create an app on the Microsoft Application Registration Portal, generate an `Application Id` and `Secret`, copy these credentials into Auth0, and enable the connection.
-
-## 1. Create an application
-
-Login to the [Microsoft Application Registration Portal](https://apps.dev.microsoft.com).
-
-Click **Add an app**.
-
-
-
-::: note
-If you have existing apps, there may be two **Add an app** buttons. Select the first.
-:::
-
-Name your new app and click **Create application**:
-
-
-
-## 2. Copy your Application Id
-
-On the **Registration** page that follows, copy the **Application Id**. This is your `client_id`.
-
-
-
-## 3. Get your password
-
-Click **Generate New Password**.
-
-Copy your password. This is your `client_secret`.
-
-
-
-## 4. Enter your callback URL
-
-Click **Add Platform**, then select **Web**.
-
-
-
-Enter the following under **Redirect URIs**:
-
-`https://${account.namespace}/login/callback`
-
-
-
-Scroll down to **Advanced Options** and make sure **Live SDK support** is checked.
-
-
-
-Click **Save**.
-
-## 5. Copy your Client ID and Client Secret
-
-Go to the [Auth0 Dashboard](${manage_url}) and select **Connections > Social** from the left menu.
-
-Select the **Microsoft** connection.
-
-Copy the `Client Id` and `Client Secret` you saved earlier into the fields on this page on Auth0.
-
-Click **Save**.
-
-
-
-## 6. Enable your apps
-
-Select the **Apps** tab of the Microsoft Account settings page in Auth0 and enable the applications you want to use with this connection.
-
-Click **Save**.
-
-
-
-## 7. Test your connection
-
-On the [Social Connections](${manage_url}/#/connections/social) page in the Auth0 dashboard, click the **Try** button next to the Microsoft connection.
-
-
-
-Click Yes to allow your Microsoft app to access your information.
-
-
-
-If you see the **It Works!** page, you have successfully configured your connection to Microsoft Account.
-
-
-
+<%= include('../../../snippets/social/microsoft-account/0') %>
+<%= include('../../../snippets/social/microsoft-account/1') %>
+<%= include('../../../snippets/social/microsoft-account/2') %>
+<%= include('../../../snippets/social/microsoft-account/3') %>
+<%= include('../../../snippets/social/microsoft-account/4') %>
+<%= include('../../../snippets/social/microsoft-account/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/miicard.md b/articles/connections/social/miicard.md
deleted file mode 100644
index 521b851abd..0000000000
--- a/articles/connections/social/miicard.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: Connect your app to miiCard
-connection: miiCard
-image: /media/connections/miicard.png
-seo_alias: miicard
-description: How to obtain a Client Id and Client Secret for miiCard.
----
-
-# Connect your app to miiCard
-
-Please contact miiCard to get [self-management](http://www.miicard.com/developers/self-management) capabilities on your miiCard account.
-
-Once this is enabled, you will be able to complete the Auth0 setup. The `Consumer Key` and `Consumer Secret` will be available on the __miiCard Business Portal__:
-
-
-
-<%= include('../_quickstart-links.md') %>
\ No newline at end of file
diff --git a/articles/connections/social/oauth2.md b/articles/connections/social/oauth2.md
index 94be304274..963d33a05e 100644
--- a/articles/connections/social/oauth2.md
+++ b/articles/connections/social/oauth2.md
@@ -1,94 +1,132 @@
---
-title: Add a generic OAuth2 Authorization Server to Auth0
-connection: Generic OAuth2 Provider
+connection: OAuth2 Provider (Generic)
image: /media/connections/oauth2.png
seo_alias: oauth2
-index: 13
-description: You can add any OAuth2 provider using the Auth0 Custom Social Connections extension.
+toc: true
+index: 15
+description: Learn how to add any OAuth2 provider using Auth0 Custom Social Connections.
+topics:
+ - connections
+ - social
+ - oauth2
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Add a generic OAuth2 Authorization Server to Auth0
+# Connect Apps to Generic OAuth2 Authorization Servers
-The most common [identity providers](/identityproviders) are readily available on Auth0's dashboard. However, you can add any other OAuth2 provider using the **Custom Social Connections** [extension](${manage_url}/#/extensions).
+The most common [identity providers](/identityproviders) are available in [Auth0's Dashboard](${manage_url}) and in the [Auth0 Marketplace](https://marketplace.auth0.com/features/social-connections). However, you can add any other OAuth2 provider using a **Custom Social Connection**.
-
+To create a new Custom Social Connection, navigate to [**Auth0 Dashboard > Authentication > Social**](${manage_url}/#/connections/social), click **Create Connection**, scroll to the bottom of the list, and click **Create Custom**.
-::: note
-For details on how to install and configure the extension, refer to [Auth0 Extension: Custom Social Connections](/extensions/custom-social-extensions).
-:::
-
-## The `fetchUserProfile` script
+The form that appears contains several fields that you must use to configure the custom connection:
-A custom `fetchUserProfile` script will be called after the user has logged in with the OAuth2 provider. Auth0 will execute this script to call the OAuth2 provider API and get the user profile:
+- **Connection Name**: Logical identifier for the Connection you are creating. This name cannot be changed, must start and end with an alphanumeric character, and can only contain alphanumeric characters and dashes.
+- **Authorization URL**: URL to which users are redirected to log in.
+ :::note
+ Do not attempt to set the OAuth2 `response_mode` parameter in the authorization URL. This connection only supports the default `response_mode` (`query`).
+ :::
+- **Token URL**: URL used to exchange the received authorization code for access tokens and, if requested, ID tokens.
+- **Scope** - `scope` parameters to send with the authorization request. Separate multiple scopes with spaces.
+- **Client ID**: Client ID for Auth0 as an application used to request authorization and exchange the authorization code. To get a Client ID, you will need to register with the identity provider.
+- **Client Secret**: Client Secret for Auth0 as an application used to exchange the authorization code. To get a Client Secret, you will need to register with the identity provider.
+- **Fetch User Profile Script**: Node.js script used to call a userinfo URL with the provided access token. To learn more about this script, see [Fetch User Profile Script](#fetch-user-profile-script).
-```js
-function(access_token, ctx, callback){
- // call the oauth2 provider and return a profile
- // here we are returning a "mock" profile, you can use this to start with to test the flow.
- var profile = {
- user_id: '123',
- given_name: 'Eugenio',
- family_name: 'Pace',
- email: 'eugenio@mail.com'
- };
-
- callback(null, profile);
-}
-```
+:::note
+When configuring the custom identity provider, use the callback URL `https://${account.namespace}/login/callback`.
+:::
-The `access_token` parameter is used for authenticating requests to the provider's API.
+Once you create the custom connection, you will see the **Applications** view. Here, you can enable and disable applications for which you would like the connection to appear.
-::: note
-We recommend using the field names from the [normalized profile](/user-profile#normalized-user-profile).
-:::
+## Fetch User Profile Script
-For example, the following code will retrieve the user profile from the **GitHub** API:
+The fetch user profile script is called after the user has logged in with the OAuth2 provider. Auth0 executes this script to call the OAuth2 provider API and get the user profile:
```js
-function(access_token, ctx, callback) {
- request.get('https://api.github.com/user', {
- 'headers': {
- 'Authorization': 'Bearer ' + access_token,
- 'User-Agent': 'Auth0'
- }
- }, function(e,r,b){
- if( e ) return callback(e);
- if( r.statusCode !== 200 ) return callback(new Error('StatusCode:'+r.statusCode));
- callback(null,JSON.parse(b));
- });
+function fetchUserProfile(accessToken, context, callback) {
+ request.get(
+ {
+ url: 'https://auth.example.com/userinfo',
+ headers: {
+ 'Authorization': 'Bearer ' + accessToken,
+ }
+ },
+ (err, resp, body) => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (resp.statusCode !== 200) {
+ return callback(new Error(body));
+ }
+
+ let bodyParsed;
+ try {
+ bodyParsed = JSON.parse(body);
+ } catch (jsonError) {
+ return callback(new Error(body));
+ }
+
+ const profile = {
+ user_id: bodyParsed.account.uuid,
+ email: bodyParsed.account.email
+ };
+
+ callback(null, profile);
+ }
+ );
}
```
-You can filter, add or remove anything from the profile returned from the provider. However, it is recommended that you keep this script as simple as possible. More sophisticated manipulation of user information can be achieved through the use of [Rules](/rules). One advantage of using Rules is that they apply to *any* connection.
+The `user_id` property in the returned profile is required, and the `email` property is optional but highly recommended. To learn more about what attributes can be returend, see [User Profile Root Attributes](/users/updating-user-profile-root-attributes).
-## Log in using the custom connection
+You can filter, add, or remove anything from the profile returned from the provider. However, it is recommended that you keep this script as simple as possible. More sophisticated manipulation of user information can be achieved through the use of [Rules](/rules). One advantage of using Rules is that they apply to any connection.
-You can use any of the Auth0 standard mechanisms (such as direct links, [Auth0 Lock](/libraries/lock), [auth0.js](/libraries/auth0js), and so on.) to login a user with the your custom connection.
+## Log in using the custom connection
-A direct link would look like:
+You can use any of the Auth0 standard mechanisms to log a user in with your custom connection. A direct link would look like:
```text
https://${account.namespace}/authorize
?response_type=code
&client_id=${account.clientId}
&redirect_uri=${account.callback}
- &scope=openid%20profile
- &connection=THE_NAME_OF_THE_CONNECTION
- &state=OPAQUE_VALUE
+ &scope=openid%20profile%20email
+ &connection=NAME_OF_CONNECTION
```
-To add a custom connection in Lock, you can add a custom button by following the instructions at [Adding custom connections to lock](/libraries/lock/v9/ui-customization#adding-a-new-ui-element-using-javascript) and using this link as the button `href`.
+## Modify the icon and display name
-## Pass provider-specific parameters
+To add an icon to the identity provider's login button or change the text used on the login button, you can use the `icon_url` property of the `options` object and the `display_name` property, respectively, via the [Management API](/api/management/v2#!/Connections/patch_connections_by_id).
-You can pass provider-specific parameters to the Authorization endpoint of an OAuth 2.0 providers. These can be either static or dynamic.
+:::note
+These fields will only affect how the Connection is displayed in the [New Universal Login Experience](https://auth0.com/docs/universal-login/new-experience).
+:::
-### Pass static parameters
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/connections/CONNECTION-ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ \"options\": { \"client_id\": \"...\", \"client_secret\": \"...\", \"icon_url\": \"https://cdn.example.com/assets/icon.png\", \"scripts\": { \"fetchUserProfile\": \"...\" }, \"authorizationURL\": \"https://public-auth.example.com/oauth2/authorize\", \"tokenURL\": \"https://auth.example.com/oauth2/token\", \"scope\": \"auth\" }, \"enabled_clients\": [ \"...\" ] }, \"display_name\": \"Connection Name\""
+ }
+}
+```
+
+
+
+## Pass provider-specific parameters
-To pass any static parameters, you can use the `authParams` element of the `options` when configuring an OAuth 2.0 connection via the [Management API](/api/management/v2#!/Connections/patch_connections_by_id).
+You can pass provider-specific parameters to the Authorization endpoint of OAuth 2.0 providers. These can be either static or dynamic.
-Let's use WordPress as an example, which allows you to pass an optional `blog` parameter to their OAuth 2.0 authorization endpoint (see their [OAuth 2.0 documentation](https://developer.wordpress.com/docs/oauth2/) for more information). Let's assume that you want to always request a user to grant access to the `myblog.wordpress.com` blog when logging in using WordPress.
+### Pass static parameters
-Using the Management API, you can configure the WordPress connection to always pass this value in the `blog` parameter when authorizing a user via WordPress.
+To pass static parameters (parameters that are sent with every authorization request), you can use the `authParams` element of the `options` when configuring an OAuth 2.0 connection via the [Management API](/api/management/v2#!/Connections/patch_connections_by_id). The call below will set a static parameter of `custom_param` set to `custom.param.value` on all authorization requests:
```har
{
@@ -99,18 +137,18 @@ Using the Management API, you can configure the WordPress connection to always p
],
"postData": {
"mimeType": "application/json",
- "text": "{ \"options\": { \"client_id\": \"...\", \"client_secret\": \"...\", \"authParams\": { \"blog\": \"myblog.wordpress.com\" }, \"scripts\": { \"fetchUserProfile\": \"...\" }, \"authorizationURL\": \"https://public-api.wordpress.com/oauth2/authorize\", \"tokenURL\": \"https://public-api.wordpress.com/oauth2/token\", \"scope\": \"auth\" }, \"enabled_clients\": [ \"...\" ] }"
+ "text": "{ \"options\": { \"client_id\": \"...\", \"client_secret\": \"...\", \"authParams\": { \"custom_param\": \"custom.param.value\" }, \"scripts\": { \"fetchUserProfile\": \"...\" }, \"authorizationURL\": \"https://public-auth.example.com/oauth2/authorize\", \"tokenURL\": \"https://auth.example.com/oauth2/token\", \"scope\": \"auth\" }, \"enabled_clients\": [ \"...\" ] }"
}
}
```
### Pass dynamic parameters
-There are certain circumstances where you may want to pass a dynamic value to OAuth 2.0 Identity Provider. In this case you can use the `authParamsMap` element of the `options` to specify a mapping between one of the existing additional parameters accepted by [the Auth0 `/authorize` endpoint](/api/authentication#social) to the parameter accepted by the Identity Provider.
+In certain circumstances, you may want to pass a dynamic value to an OAuth 2.0 Identity Provider. In this case, you can use the `authParamsMap` element of the `options` to specify a mapping between one of the existing additional parameters accepted by the [Auth0 `/authorize` endpoint](/api/authentication#social) to the parameter accepted by the Identity Provider.
-Using the same example of WordPress above, let's assume that you want to pass the `blog` parameter to WordPress, but you want to specify the actual value of the parameter when calling the Auth0 `/authorize` endpoint.
+Using the same example above, let's assume that you want to pass the `custom_param` parameter to the authorization endpoint, but you want to specify the actual value of the parameter when calling the Auth0 `/authorize` endpoint.
-In this case you can use one of the existing addition parameters accepted by the `/authorize` endpoint, such as `access_type`, and map that to the `blog` parameter being passed to WordPress:
+In this case, you can use one of the existing addition parameters accepted by the `/authorize` endpoint, such as `access_type`, and map that to the `custom_param` parameter:
```har
{
@@ -121,37 +159,25 @@ In this case you can use one of the existing addition parameters accepted by the
],
"postData": {
"mimeType": "application/json",
- "text": "{ \"options\": { \"client_id\": \"...\", \"client_secret\": \"...\", \"authParamsMap\": { \"blog\": \"access_type\" }, \"scripts\": { \"fetchUserProfile\": \"...\" }, \"authorizationURL\": \"https://public-api.wordpress.com/oauth2/authorize\", \"tokenURL\": \"https://public-api.wordpress.com/oauth2/token\", \"scope\": \"auth\" }, \"enabled_clients\": [ \"...\" ] }"
+ "text": "{ \"options\": { \"client_id\": \"...\", \"client_secret\": \"...\", \"authParamsMap\": { \"custom_param\": \"access_type\" }, \"scripts\": { \"fetchUserProfile\": \"...\" }, \"authorizationURL\": \"https://auth.example.com/oauth2/authorize\", \"tokenURL\": \"https://auth.example.com/oauth2/token\", \"scope\": \"auth\" }, \"enabled_clients\": [ \"...\" ] }"
}
}
```
-Now when calling the `/authorize` endpoint you can pass the name of the blog in the `access_type` parameter, and that value will in turn be passed along to the WordPress authorization endpoint in the `blog` parameter:
-
-```text
-https://${account.namespace}/authorize
- ?response_type=code
- &client_id=${account.clientId}
- &redirect_uri=${account.callback}
- &scope=openid%20profile
- &connection=wordpress
- &access_type=myblog.wordpress.com
- &state=OPAQUE_VALUE
-```
+Now when calling the `/authorize` endpoint, you can pass the access type in the `access_type` parameter, and that value will in turn be passed along to the authorization endpoint in the `custom_param` parameter.
## Pass Extra Headers
-In some instances you will need to pass extra headers to the Authorization endpoint of an OAuth 2.0 provider. To configure extra headers, open the Settings for the Connection and in the **Custom Headers** field, specify a JSON object with the custom headers as key-value pairs:
+In some instances, you will need to pass extra headers to the Token endpoint of an OAuth 2.0 provider. To configure extra headers, open the Settings for the Connection, and in the **Custom Headers** field, specify a JSON object with the custom headers as key-value pairs:
```json
{
"Header1" : "Value",
"Header2" : "Value"
- // ...
}
```
-Let us use an example where an Identity Provider may require you to pass an `Authorization` header with [Basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) credentials. In this scenario you can specify the following JSON object in the **Custom Headers** field:
+Let's use an example where an Identity Provider may require you to pass an `Authorization` header with [Basic access authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) credentials. In this scenario, you can specify the following JSON object in the **Custom Headers** field:
```json
{
@@ -159,14 +185,10 @@ Let us use an example where an Identity Provider may require you to pass an `Aut
}
```
-Where `[your credentials]` is the actual credentials which you need to send to the Identity Provider.
+Where `[your credentials]` are the actual credentials to send to the Identity Provider.
## Keep Reading
-::: next-steps
-* [Adding custom connections to lock](/libraries/lock/v9/ui-customization#adding-a-new-ui-element-using-javascript)
-* [Generic OAuth2 or OAuth1 examples](/oauth2-examples)
-* [Identity Providers supported by Auth0](/identityproviders)
+* [Social Identity Providers](https://auth0.com/docs/connections/identity-providers-social)
+* [All Identity Providers supported by Auth0](/identityproviders)
* [Identity Protocols supported by Auth0](/protocols)
-* [Add a generic OAuth1 Authorization Server to Auth0](/oauth1)
-:::
diff --git a/articles/connections/social/paypal-sandbox.md b/articles/connections/social/paypal-sandbox.md
new file mode 100644
index 0000000000..f03edf9368
--- /dev/null
+++ b/articles/connections/social/paypal-sandbox.md
@@ -0,0 +1,27 @@
+---
+title: Connect Apps to PayPal Sandbox
+connection: PayPal Sandbox
+image: /media/connections/paypal.png
+seo_alias: paypal
+toc: true
+public: true
+index: 24
+description: Learn how to add login functionality to your app with PayPal Sandbox. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - connections
+ - social
+ - paypal
+ - sandbox
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+ - add-login
+---
+<%= include('../../../snippets/social/paypal-sandbox/0') %>
+<%= include('../../../snippets/social/paypal-sandbox/1') %>
+<%= include('../../../snippets/social/paypal-sandbox/2') %>
+<%= include('../../../snippets/social/paypal-sandbox/3') %>
+<%= include('../../../snippets/social/paypal-sandbox/4') %>
+<%= include('../../../snippets/social/paypal-sandbox/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/paypal.md b/articles/connections/social/paypal.md
index b2a1159242..805085dd6a 100644
--- a/articles/connections/social/paypal.md
+++ b/articles/connections/social/paypal.md
@@ -1,79 +1,25 @@
---
-title: Connect your app to PayPal
+title: Connect Apps to PayPal
connection: PayPal
image: /media/connections/paypal.png
seo_alias: paypal
-index: 10
-description: How to obtain a Client Id and Client Secret for PayPal.
toc: true
+public: true
+index: 23
+description: Learn how to add login functionality to your app with PayPal. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - connections
+ - social
+ - paypal
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to PayPal
-
-To configure an OAuth connection with PayPal, register your Auth0 Application on the [**PayPal Developer Portal**](https://developer.paypal.com/).
-
-## 1. Registering Your Auth0 Application Using the PayPal Developer Portal
-
-Go to the [PayPal Developer Portal](https://developer.paypal.com/) and log in with your PayPal credentials. Click on **Dashboard** in the upper-right corner.
-
-
-
-You will be directed to the **My Apps & Credentials** page. Scroll down to under the **REST API Apps** section, click **Create App**.
-
-
-
-On the **Create New App** page, provide a value for **App Name** and click **Create App**:
-
-
-
-## 2. Obtain Your PayPal Client ID and Secret
-
-Once PayPal has created your app, you will be shown the API credentials for this particular application. Copy both the **Client ID** and **Secret** values (the Secret value is initially hidden) for later use.
-
-
-
-## 3. Provide PayPal with Information About Your Auth0 Client
-
-Scroll down to the **Sandbox App Settings** section and **Show** the **Return URL** box. Enter the following value:
-
-`https://${account.namespace}/login/callback`
-
-
-
-If you would like to control the scope of access to customer data (such as profile information, email address, home address, and phone number) through Auth0, you need to enable access to this information by selecting the desired attributes under the **Advanced Options**, which becomes available to you if you enable the **Log In with PayPal** feature.
-
-
-
-Click **Save**:
-
-## 4. Provide Your PayPal Client Id and Secret to Your Auth0 Application
-
-Go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 Dashboard. Under the **Social** page, click to enable **PayPal**.
-
-
-
-Paste in the **Client Id** and **Secret** from the **PayPal Developer Portal** into the **App ID** and **App Secret** fields on this page on Auth0, respectively, then click **Save**.
-
-
-
-## 5. Enable and Test the Connection
-
-Switch the **Paypal** connection in the dashboard to enabled. Then under **Applications**, choose which of your applications you want to enable this connection and then click **SAVE**.
-
-
-
-Now you should see a **TRY** button for the **Paypal** connection.
-
-
-
-This allows you to test your connection to see if it has been configured properly.
-
-::: note
-The Target URL field that you enter can take up to 3 hours for the change to go into effect with Paypal. This can cause the connection to fail until it is updated.
-:::
-
-## Additional Information
-
-[Paypal Docs](https://developer.paypal.com/docs/)
-
+<%= include('../../../snippets/social/paypal/0') %>
+<%= include('../../../snippets/social/paypal/1') %>
+<%= include('../../../snippets/social/paypal/2') %>
+<%= include('../../../snippets/social/paypal/3') %>
+<%= include('../../../snippets/social/paypal/4') %>
+<%= include('../../../snippets/social/paypal/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/pinterest.md b/articles/connections/social/pinterest.md
new file mode 100644
index 0000000000..ed39fbed47
--- /dev/null
+++ b/articles/connections/social/pinterest.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Pinterest
+connection: Pinterest
+image: /media/connections/pinterest.png
+seo_alias: pinterest
+description: Learn how to add login functionality to your app with Pinterest. You will need to obtain a Client ID and Client Secret for Pinterest.
+toc: true
+public: false
+index: 6
+topics:
+ - connections
+ - social
+ - pinterest
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/pinterest/0') %>
+<%= include('../../../snippets/social/pinterest/1') %>
+<%= include('../../../snippets/social/pinterest/2') %>
+<%= include('../../../snippets/social/pinterest/3') %>
+<%= include('../../../snippets/social/pinterest/4') %>
+<%= include('../../../snippets/social/pinterest/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/planning-center.md b/articles/connections/social/planning-center.md
index 2d9e8d9c14..1f05c7844e 100644
--- a/articles/connections/social/planning-center.md
+++ b/articles/connections/social/planning-center.md
@@ -1,45 +1,25 @@
---
-title: Connect your app to Planning Center
+title: Connect Apps to Planning Center
connection: Planning Center
image: /media/connections/planning-center.png
seo_alias: planning-center
-description: How to obtain a Client Id and Client Secret for Planning Center.
+description: Learn how to add login functionality to your app with Planning Center. You will need to get a Client Id and Client Secret for Planning Center.
toc: true
+public: true
+index: 25
+topics:
+ - connections
+ - social
+ - planning-center
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Planning Center
-
-To configure an OAuth2 connection with Planning Center Online, you will need to register Auth0 with Planning Center on their Developer portal.
-
-## 1. Log into the Planning Center Developer portal
-
-Go to the [Planning Center Developer](https://api.planningcenteronline.com/) portal. Log in with your credentials and click **Register** on the **Developer Applications** page:
-
-
-
-## 2. Complete information about your instance of Auth0
-
-Complete the form. In the **Authorization callback URLs** field, enter this URL:
-
- https://${account.namespace}/login/callback
-
-and click **Submit**:
-
-
-
-## 3. Get your *Client ID* and *Secret*
-
-Once your app is registered, your `Client Id` and `Secret` will be displayed:
-
-
-
-## 4. Copy your *Client Id* and *Secret*
-
-Go to the [Social Connections](${manage_url}/#/connections/social) page of your Auth0 Dashboard and select **Planning Center**.
-
-Copy the `Client Id` and `Secret` from the **Developer Applications** page of the Planning Center Developer portal into the fields on this page on Auth0.
-
-
-
+<%= include('../../../snippets/social/planning-center/0') %>
+<%= include('../../../snippets/social/planning-center/1') %>
+<%= include('../../../snippets/social/planning-center/2') %>
+<%= include('../../../snippets/social/planning-center/3') %>
+<%= include('../../../snippets/social/planning-center/4') %>
+<%= include('../../../snippets/social/planning-center/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/quickbooks-online.md b/articles/connections/social/quickbooks-online.md
new file mode 100644
index 0000000000..739f4c3141
--- /dev/null
+++ b/articles/connections/social/quickbooks-online.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to QuickBooks Online
+connection: QuickBooks Online
+image: /media/connections/quickbooks.png
+seo_alias: quickbooks-online
+description: Learn how to add login functionality to your app with QuickBooks Online. You will need to obtain a Client ID and Client Secret for QuickBooks Online.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - quickbooks-online
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/quickbooks-online/0') %>
+<%= include('../../../snippets/social/quickbooks-online/1') %>
+<%= include('../../../snippets/social/quickbooks-online/2') %>
+<%= include('../../../snippets/social/quickbooks-online/3') %>
+<%= include('../../../snippets/social/quickbooks-online/4') %>
+<%= include('../../../snippets/social/quickbooks-online/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/renren.md b/articles/connections/social/renren.md
index d7b001498c..e6a74ba09f 100644
--- a/articles/connections/social/renren.md
+++ b/articles/connections/social/renren.md
@@ -1,43 +1,25 @@
---
-title: Connect your app to RenRen
+title: Connect Apps to RenRen
connection: RenRen
image: /media/connections/renren.png
seo_alias: renren
-description: How to obtain an API Key and Secret Key for RenRen.
+description: Learn how to add login functionality to your app with RenRen. You will need to obtain an API Key and Secret Key for RenRen.
toc: true
+public: true
+index: 26
+topics:
+ - connections
+ - social
+ - renren
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to RenRen
-
-To configure a RenRen OAuth2 connection, you will need to register Auth0 on the RenRen integration portal.
-
-## 1. Create a new App
-
-Log into the RenRen [integration portal](http://app.renren.com/developers) and click **Create New App**:
-
-
-
-## 2. Enter app information
-
-Complete the required information on this page. Enter the following value for the *callback URL*:
-
- https://${account.namespace}/login/callback
-
-Click **Create App**.
-
-
-
-## 3. Get your *API Key* and *Secret Key*
-
-Once the app is created, the `API Key` and `Secret Key` will be displayed on the following page:
-
-
-
-## 4. Copy your *API Key* and *Secret Key*
-
-Go to the [Social Connections](${manage_url}/#/connections/social) section of your Auth0 Dashboard and choose **RenRen**. Copy the `API Key` and `Secret Key` from the **New App** page on RenRen into fields on this page on Auth0:
-
-
-
+<%= include('../../../snippets/social/renren/0') %>
+<%= include('../../../snippets/social/renren/1') %>
+<%= include('../../../snippets/social/renren/2') %>
+<%= include('../../../snippets/social/renren/3') %>
+<%= include('../../../snippets/social/renren/4') %>
+<%= include('../../../snippets/social/renren/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/reprompt-permissions.md b/articles/connections/social/reprompt-permissions.md
index 96a4b678dc..dfe3a2a4b8 100644
--- a/articles/connections/social/reprompt-permissions.md
+++ b/articles/connections/social/reprompt-permissions.md
@@ -1,8 +1,15 @@
---
-description: How to handle declined authorization permissions and how to re-prompt for these permissions.
+description: Describes how to handle declined authorization permissions and how to re-prompt for these permissions.
+topics:
+ - connections
+ - social
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Handling Declined Authorization Permissions
+# Handle Declined Authorization Permissions
When your users are authorizing your application, some providers (such as Facebook) allow the user to select the attributes they wish to share.
@@ -10,17 +17,15 @@ By default, this selection is made only when the user authorizes the app for the
In such instances, your user will need to be re-prompted to grant permission to the required attribute(s) to login.
-## How to re-prompt for permissions
+## Re-prompt for permissions
By setting the **prompt=consent** parameter when calling the [/authorize](/api/authentication/reference#social) endpoint of the [Authorization API](/api/authentication), your user will be prompted again to grant permissions for your application.
-This parameter can also be set using [Lock](/libraries/lock) as an [Authentication Parameter](/libraries/lock/sending-authentication-parameters) with **prompt: 'consent'**.
+This parameter can also be set using Lock as an [Authentication Parameter](/libraries/lock/sending-authentication-parameters) with **prompt: 'consent'**.
Alternatively, you can set this with [Auth0.js](https://github.com/auth0/auth0.js) using **prompt: 'consent'**.
-## Learn More
+## Keep reading
-::: next-steps
-* [Click here to learn more about handling declined Facebook permissions.](https://developers.facebook.com/docs/facebook-login/handling-declined-permissions)
-* [Click here to learn more about GitHub scopes](https://developer.github.com/v3/oauth/#scopes)
-:::
\ No newline at end of file
+* [Learn more about handling declined Facebook permissions](https://developers.facebook.com/docs/facebook-login/handling-declined-permissions)
+* [Learn more about GitHub scopes](https://developer.github.com/v3/oauth/#scopes)
\ No newline at end of file
diff --git a/articles/connections/social/salesforce-community.md b/articles/connections/social/salesforce-community.md
new file mode 100644
index 0000000000..7288863f0a
--- /dev/null
+++ b/articles/connections/social/salesforce-community.md
@@ -0,0 +1,30 @@
+---
+title: Connect Apps to Salesforce Community
+connection: Salesforce Community
+image: /media/connections/salesforce.png
+seo_alias: salesforce-community
+toc: true
+public: true
+index: 29
+description: Learn how to add login functionality to your app with Salesforce Community. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - connections
+ - social
+ - salesforce
+ - salesforce-community
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+ - add-login
+---
+<%= include('../../../snippets/social/salesforce-community/0') %>
+<%= include('../../../snippets/social/salesforce-community/1') %>
+<%= include('../../../snippets/social/salesforce-community/2') %>
+<%= include('../../../snippets/social/salesforce-community/3') %>
+<%= include('../../../snippets/social/salesforce-community/4') %>
+<%= include('../../../snippets/social/salesforce-community/5') %>
+<%= include('../../../snippets/social/salesforce-community/6') %>
+<%= include('../../../snippets/social/salesforce-community/7') %>
+<%= include('../../../snippets/social/salesforce-community/8') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/salesforce-sandbox.md b/articles/connections/social/salesforce-sandbox.md
new file mode 100644
index 0000000000..78bc4bf722
--- /dev/null
+++ b/articles/connections/social/salesforce-sandbox.md
@@ -0,0 +1,26 @@
+---
+title: Connect Apps to Salesforce Sandbox
+connection: Salesforce Sandbox
+image: /media/connections/salesforce.png
+seo_alias: salesforce-sandbox
+toc: true
+public: true
+index: 28
+description: Learn how to add login functionality to your app with Salesforce Sandbox. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - connections
+ - social
+ - salesforce
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+ - add-login
+---
+<%= include('../../../snippets/social/salesforce-sandbox/0') %>
+<%= include('../../../snippets/social/salesforce-sandbox/1') %>
+<%= include('../../../snippets/social/salesforce-sandbox/2') %>
+<%= include('../../../snippets/social/salesforce-sandbox/3') %>
+<%= include('../../../snippets/social/salesforce-sandbox/4') %>
+<%= include('../../../snippets/social/salesforce-sandbox/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/salesforce.md b/articles/connections/social/salesforce.md
index cfe4dab87e..c5c0ad838e 100644
--- a/articles/connections/social/salesforce.md
+++ b/articles/connections/social/salesforce.md
@@ -1,72 +1,26 @@
---
-title: Connect your app to Salesforce
+title: Connect Apps to Salesforce
connection: Salesforce
image: /media/connections/salesforce.png
seo_alias: salesforce
-index: 6
-description: How to connect your app to Salesforce using Auth0.
toc: true
+public: true
+index: 27
+description: Learn how to add login functionality to your app with Salesforce. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - connections
+ - social
+ - salesforce
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Salesforce
-
-To configure a Salesforce OAuth2 connection you will need to register your Auth0 tenant on their **Administer** panel.
-
-## 1. Register a New App
-
-Log into [Salesforce](https://login.salesforce.com/). Click on **Settings > Setup** in the upper right, next to your account name.
-
-
-
-Navigate to **Platform Tools > Apps**. Under **App Manager**, click **New Connected App**:
-
-
-
-## 2. Complete the New Connected App form
-
-1. Enter the required basic information (*Connected App Name*, *API Name* and *Contact Email*).
-2. Select **Enable OAuth Settings** under **API (Enable OAuth Settings)**.
-3. Enter your callback URL: `https://${account.namespace}/login/callback`
-4. Add *Access your basic information* to the **Selected OAuth Scopes**.
-5. Click **Save**.
-
- 
-
-## 3. Get your Consumer Key and Consumer Secret
-
-Once your app is registered, the page will diplay your `Consumer Key` and `Consumer Secret`:
-
-
-
-## 4. Copy your Consumer Key and Consumer Secret
-
-Go to your Auth0 [Dashboard](${manage_url}/#/connections/social) and select **Connections > Social**, then choose **Salesforce**.
-
-Copy the `Consumer Key` and `Consumer Secret` from the **Connected App** page of your app on Salesforce into the fields on this page on Auth0 and click **Save**:
-
-
-
-## Salesforce Community Authentication
-
-Authenticating users in a Salesforce community uses different endpoints that the regular Salesforce app.
-
-The authorization URL for a Community site will be: `https://{name of your community}.force.com/{community path}/oauth2/authorize`.
-
-In this example, the community is named __contoso__ and it is for __customers__:
-
-```text
-https://contoso.force.com/customers/oauth2/authorize?
-response_type=token&
-client_id=your_app_id&
-redirect_uri=your_redirect_uri
-```
-
-Notice that Auth0 will automatically pass all required OAuth2 parameters (such as `response_type`, `client_id`, and so on) and concatenate other elements to the path (such as `oauth2/authorize`). All that is required is that you configure the __base__ community site URL: `https://contoso.force.com/customers`.
-
-::: note
-For full details refer to this [Salesforce article](http://www.salesforce.com/us/developer/docs/chatterapi/Content/quickstart_communities.htm).
-:::
-
-It is common to customize the login page for __Community__ sites. If you do so, remember that the login page is part of the login transaction and you must honor the OAuth2 flow. [This sample](https://github.com/salesforceidentity/basic-custom-login) provides details on how to do it properly.
-
+<%= include('../../../snippets/social/salesforce/0') %>
+<%= include('../../../snippets/social/salesforce/1') %>
+<%= include('../../../snippets/social/salesforce/2') %>
+<%= include('../../../snippets/social/salesforce/3') %>
+<%= include('../../../snippets/social/salesforce/4') %>
+<%= include('../../../snippets/social/salesforce/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/shop.md b/articles/connections/social/shop.md
new file mode 100644
index 0000000000..4e631a01ed
--- /dev/null
+++ b/articles/connections/social/shop.md
@@ -0,0 +1,28 @@
+---
+title: Connect Apps to Shop
+connection: Shop
+image: /media/connections/shop.png
+seo_alias: shop
+toc: true
+public: true
+index: 39
+description: Learn how to add login functionality to your app with Shop. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - authentication
+ - connections
+ - social
+ - shop
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/shop/0') %>
+<%= include('../../../snippets/social/shop/1') %>
+<%= include('../../../snippets/social/shop/2') %>
+<%= include('../../../snippets/social/shop/3') %>
+<%= include('../../../snippets/social/shop/4') %>
+<%= include('../../../snippets/social/shop/5') %>
+<%= include('../../../snippets/social/shop/6') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/shopify.md b/articles/connections/social/shopify.md
index c9c4d4d903..ddafd35d4b 100644
--- a/articles/connections/social/shopify.md
+++ b/articles/connections/social/shopify.md
@@ -1,94 +1,27 @@
---
-title: Connect your app to Shopify
+title: Connect Apps to Shopify
connection: Shopify
image: /media/connections/shopify.png
seo_alias: shopify
-description: How to connect your Auth0 app to Shopify.
toc: true
+public: true
+index: 30
+description: Learn how to add login functionality to your app with Shopify. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
+topics:
+ - authentication
+ - connections
+ - social
+ - shopify
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Shopify
-
-To connect your Auth0 app to Shopify, you will need to create an app on the Shopify Partner portal to generate **API Key** and **Shared Secret**, copy these credentials into your Auth0 settings, and enable the connection.
-
-::: panel-warning User profile not available
-Due to Shopify's OAuth implementation, successful user authentication returns the **Shop** profile, not the user profile.
-:::
-
-## 1. Create an app on the Shopify Partner portal
-
-Login to the [Shopify Partner](https://app.shopify.com/services/partners) portal. Select **Apps** in the left nav and click **Create a new app**:
-
-
-
-
-## 2. Create your app
-
-Complete the form.
-
-In the fields below, enter the following:
-
-* **App URL**: `https://YOUR_TENANT.auth0.com`
-* **Redirection URL**: `https://YOUR_TENANT.auth0.com/login/callback`
-
-
-
-Click **Create app**.
-
-## 3. Get your API Key and Shared Secret
-
-On the page that follows, your `API Key` and `Shared Secret` will be displayed. Save these for use in the next step.
-
-
-
-## 4. Enter your API Key and Shared Secret into Auth0
-
-In a separate window, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 Dashboard.
-
-Select Shopify:
-
-
-
-Copy the `API Key` and `Shared Secret` from the Apps page on Shopify into the fields on this page on Auth0.
-
-Enter your **Shop name**.
-
-Select the **Permissions** you want to enable.
-
-Click **SAVE**.
-
-
-
-## 5. Enable the Connection
-
-Go to the **Apps** tab of the Shopify connection on Auth0 and select each of your existing Auth0 apps for which you want to enable this connection:
-
-
-
-## 6. Test the connection
-
-Close the Settings window to return to the **Connections > Social** section of the Auth0 dashboard.
-
-A TRY icon will now be displayed next to the Shopify logo:
-
-
-
-Click TRY.
-
-Login to your Shopify store.
-
-Click **Install app** to allow your app access.
-
-
-
-If you have configured everything correctly, you will see the It works!!! page:
-
-
-
-::: panel Shopify Multipass
-You can use Shopify's [Multipass](https://help.shopify.com/api/reference/multipass) feature to automatically authenticate users who have already been verified by Auth0 on Shopify.
-:::
-
+<%= include('../../../snippets/social/shopify/0') %>
+<%= include('../../../snippets/social/shopify/1') %>
+<%= include('../../../snippets/social/shopify/2') %>
+<%= include('../../../snippets/social/shopify/3') %>
+<%= include('../../../snippets/social/shopify/4') %>
+<%= include('../../../snippets/social/shopify/5') %>
<%= include('../_quickstart-links.md') %>
-
-
diff --git a/articles/connections/social/slack.md b/articles/connections/social/slack.md
new file mode 100644
index 0000000000..727f5e3f5c
--- /dev/null
+++ b/articles/connections/social/slack.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Slack
+connection: Slack
+image: /media/connections/slack.png
+seo_alias: slack
+description: Learn how to add login functionality to your app with Slack. You will need to obtain a Client ID and Client Secret for Slack.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - slack
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/slack/0') %>
+<%= include('../../../snippets/social/slack/1') %>
+<%= include('../../../snippets/social/slack/2') %>
+<%= include('../../../snippets/social/slack/3') %>
+<%= include('../../../snippets/social/slack/4') %>
+<%= include('../../../snippets/social/slack/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/soundcloud.md b/articles/connections/social/soundcloud.md
index eb349ff5e6..6c41a9add6 100644
--- a/articles/connections/social/soundcloud.md
+++ b/articles/connections/social/soundcloud.md
@@ -1,54 +1,59 @@
---
-title: Connect your app to SoundCloud
+title: Connect Apps to SoundCloud
connection: SoundCloud
-index: 5
+toc: true
+public: false
+index: 31
image: /media/connections/soundcloud.png
seo_alias: soundcloud
-description: How to obtain a Client Id and Client Secret for SoundCloud.
-toc: true
+description: Learn how to add login functionality to your app with SoundCloud. You will need to obtain a Client Id and Client Secret for SoundCloud.
+topics:
+ - connections
+ - social
+ - soundcloud
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Connect your app to SoundCloud
-
-To configure an OAuth 2.0 connection with SoundCloud, you will need to register your Auth0 Application with SoundCloud using their [Developer Portal](http://developers.soundcloud.com/).
+# Connect Apps to SoundCloud
-## 1. Register Your App and Obtain API Credentials with SoundCloud
+You can add functionality to your web app that allows your users to log in with SoundCloud.
-::: panel-warning SoundCloud App Registration
-SoundCloud's manual application registration process is currently closed, so **new applications cannot be registered**. Furthermore, as noted below, SoundCloud does **not** have an automated process to register your app. Auth0 does not have any control over this process, you must apply to SoundCloud and work with them to get your application configured. Only after SoundCloud approves your application can you use SoundCloud with Auth0.
+::: panel-warning Restricted SoundCloud App Registration
+SoundCloud's manual application registration process is currently closed, so **new applications cannot be registered**. SoundCloud does **not** have an automated process to register your app. You must apply to SoundCloud and work with them to get your application configured which can take up to 2 weeks. Only after SoundCloud approves your application can you use SoundCloud with Auth0. See [How to Request a SoundCloud API Key](https://support.appmachine.com/hc/en-us/articles/115000057244-How-to-request-a-SoundCloud-API-key) for details.
:::
-Navigate to the [SoundCloud Developer Portal](http://developers.soundcloud.com/). Using the navigation menu on the right side, click on **Register a new app**:
-
-
-
-You will be asked to fill out a Developer Application (which is a Google Forms document):
-
-
+## Prerequisites
-This provides SoundCloud information about your Auth0 Application.
+Before connecting your Auth0 app to SoundCloud, you must have a [SoundCloud Developer](http://developers.soundcloud.com/) account.
-Once you have completed and submitted your application, you will be contacted by the SoundCloud team with further instructions on how to proceed. Only at this point will you be given the appropriate API credentials to complete the integration.
+## Steps
-## 2. Set Up a SoundCloud Social Connection in Auth0
+To connect your app to SoundCloud, you will:
-Once your Auth0 Application has been added to your SoundCloud account, you can get the `Client ID` and `Client Secret` necessary for the Auth0 Connection Settings.
+1. [Set up your app in SoundCloud](#set-up-your-app-in-soundcloud)
+2. [Create and enable a connection in Auth0](#create-and-enable-a-connection-in-auth0)
+3. [Test the connection](#test-the-connection)
-
+### Set up your app in SoundCloud
-Be sure to provide the following as your `Redirect URI for Authentication` on the SoundCloud dashboard: `https://${account.namespace}/login/callback`
+1. [Create a new app on your SoundCloud profile](https://soundcloud.com/you/apps/new), and complete your SoundCloud Application Registration by following the steps on the screen.
+ * Find your SoundCloud profile URL by [logging into SoundCloud](https://soundcloud.com/) and clicking your profile name in the top-right corner of the screen. Once navigated to your profile, your profile URL is displayed in your browser's address bar.
+ * Answer **Will your app authenticate users?** with `No, my app will only use publicly accessible resources`.
-Go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard and enable **SoundCloud**.
+ Your app will be in review for a maximum period of two weeks. Once approved, you will be able to use your SoundCloud API key to stream music from SoundCloud within your AppMachine app.
-
+2. When your request is approved, you will receive your own SoundCloud **Client ID**. Enter it in the **Music** block in the appropriate field under **Settings: Client ID**.
-You will be prompted to provide your SoundCloud `Client ID` and `Client Secret`.
+### Create and enable a connection in Auth0
-
+[Set up the SoundCloud social connection](/dashboard/guides/connections/set-up-connections-social) in Auth0. Make sure you have the generated **Client ID** and **Client Secret**.
-**Save** your settings. Switch to the *Applications* tab, and select the Application(s) you want to use the SoundCloud integration. **Save** again.
+### Test the connection
-
+You're ready to [test your connection](/dashboard/guides/connections/test-connections-social). After logging in, you'll be prompted to allow your app access. To do so, click **Install unlisted app**.
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/spotify.md b/articles/connections/social/spotify.md
new file mode 100644
index 0000000000..24a9ab8aa7
--- /dev/null
+++ b/articles/connections/social/spotify.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Spotify
+connection: Spotify
+image: /media/connections/spotify.png
+seo_alias: spotify
+description: Learn how to add login functionality to your app with Spotify. You will need to obtain a Client ID and Client Secret for Spotify.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - spotify
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/spotify/0') %>
+<%= include('../../../snippets/social/spotify/1') %>
+<%= include('../../../snippets/social/spotify/2') %>
+<%= include('../../../snippets/social/spotify/3') %>
+<%= include('../../../snippets/social/spotify/4') %>
+<%= include('../../../snippets/social/spotify/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/stripe-connect.md b/articles/connections/social/stripe-connect.md
new file mode 100644
index 0000000000..e7ddb3e6ff
--- /dev/null
+++ b/articles/connections/social/stripe-connect.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Stripe Connect
+connection: Stripe Connect
+image: /media/connections/stripe.png
+seo_alias: stripe-connect
+description: Learn how to add login functionality to your app with Stripe Connect. You will need to obtain a Client ID and Client Secret for Stripe Connect.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - stripe-connect
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/stripe-connect/0') %>
+<%= include('../../../snippets/social/stripe-connect/1') %>
+<%= include('../../../snippets/social/stripe-connect/2') %>
+<%= include('../../../snippets/social/stripe-connect/3') %>
+<%= include('../../../snippets/social/stripe-connect/4') %>
+<%= include('../../../snippets/social/stripe-connect/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/thecity.md b/articles/connections/social/thecity.md
deleted file mode 100644
index 506f160dd5..0000000000
--- a/articles/connections/social/thecity.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: Connect your app to The City
-connection: The City
-image: /media/connections/thecity.png
-seo_alias: thecity
-description: How to obtain an App ID and Secret with The City.
-toc: true
----
-
-# Connect your app to The City
-
-To connect your Auth0 app to The City, you will need to create a plugin as an administrator on your The City portal.
-
-## 1. Log in into The City portal
-
-Log in into your The City portal, and select __Admin__:
-
-
-
-## 2. Create new Plugin
-
-Select __API > Plugin > Create plugin__:
-
-
-
-Complete the form using this callback URL: `https://${account.namespace}/login/callback`
-
-
-
-Press __Create__
-
-## 3. Get your App ID & Secret
-
-Once the application is created, enter your new `App ID` and `Secret` into the connection settings in Auth0.
-
-
-
-<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/twitch.md b/articles/connections/social/twitch.md
new file mode 100644
index 0000000000..8812a908db
--- /dev/null
+++ b/articles/connections/social/twitch.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Twitch
+connection: Twitch
+image: /media/connections/twitch.png
+seo_alias: twitch
+description: Learn how to add login functionality to your app with Twitch. You will need to obtain a Client ID and Client Secret for Twitch.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - twitch
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/twitch/0') %>
+<%= include('../../../snippets/social/twitch/1') %>
+<%= include('../../../snippets/social/twitch/2') %>
+<%= include('../../../snippets/social/twitch/3') %>
+<%= include('../../../snippets/social/twitch/4') %>
+<%= include('../../../snippets/social/twitch/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/twitter.md b/articles/connections/social/twitter.md
index 0598cf5a1f..b3eaa6dbb5 100644
--- a/articles/connections/social/twitter.md
+++ b/articles/connections/social/twitter.md
@@ -1,88 +1,28 @@
---
-title: Connect your app to Twitter
+title: Connect Apps to Twitter
connection: Twitter
image: /media/connections/twitter.png
-description: This page shows you how to connect your Auth0 application to Twitter. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
seo_alias: twitter
-index: 8
+description: Learn how to add login functionality to your app with Twitter. You will need to generate keys, copy these into your Auth0 settings, and enable the connection.
toc: true
+public: true
+index: 32
+topics:
+ - connections
+ - social
+ - twitter
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-# Connect your app to Twitter
-
-To connect your Auth0 application to Twitter, you will need to generate **Consumer** and **Secret** Keys in a Twitter application, copy these into your Auth0 settings, and enable the connection.
-
-## 1. Create a Twitter application
-
-1. Login to [Twitter Application Management](https://apps.twitter.com/).
-
-2. Click **Create New App**:
-
- 
-
-3. Provide the required information. For **Callback URL**, enter `https://${account.namespace}/login/callback`
-
- 
-
-4. Agree to the *Developer Agreement* and click **Create your Twitter Application**.
-
-5. Once the app is created, go to the **Settings** tab and verify that the **Allow this application to be used to Sign in with Twitter** option is selected.
-
- 
-
-## 2. Get your Consumer Key and Consumer Secret
-
-1. Your **Consumer Key** and **Consumer Secret** will be displayed in the **Keys and Access Tokens** tab of your app on Twitter:
-
- 
-
-2. Leave this window open.
-
-## 3. Copy your Consumer Key and Consumer Secret in Auth0
-
-1. In a separate window, login to the [Auth0 Dashboard](${manage_url}) and select **Connections > Social** in the left navigation.
-
-2. Select the connection with the Twitter logo to access this connection's **Settings** page.
-
-3. Copy the **Consumer Key** and **Consumer Secret** from your app's **Keys and Access Tokens** tab on Twitter into the fields on this page on Auth0.
-
- 
-
-4. Click **Save**.
-
-::: panel Twitter Profile Attribute Permissions
-Unlike many social identity providers, Twitter manages profile attribute permissions at the application level. By default, your application will be granted *Read* and *Write* permissions. You can customize these in the **Permissions** section of the [Twitter Application Management](https://apps.twitter.com) page. For more information, see: [Application Permission Model](https://dev.twitter.com/oauth/overview/application-permission-model).
-:::
-
-## 4. Enable the connection
-
-1. Go to the **Applications** tab of the Twitter connection on Auth0 and select each of your existing Auth0 applications for which you want to enable this connection:
-
- 
-
-2. Click **Save**.
-
-## 5. Test your connection
-
-1. Go back to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard. If you have configured your app correctly, you will see a **Try** icon next to the Twitter logo:
-
- 
-
-2. Click the Twitter logo to return to the **Settings** page of this connection and click **Try**:
-
- 
-
-3. You will be asked to sign-in to Twitter to authorize your new app to access your Twitter account:
-
- 
-
-4. If you have configured everything correctly, you will see the **It works!!!** page:
-
- 
-
-## 6. Access Twitter API
-
-<%= include('../_call-api', {
- "idp": "Twitter"
-}) %>
-
+<%= include('../../../snippets/social/twitter/0') %>
+<%= include('../../../snippets/social/twitter/1') %>
+<%= include('../../../snippets/social/twitter/2') %>
+<%= include('../../../snippets/social/twitter/3') %>
+<%= include('../../../snippets/social/twitter/4') %>
+<%= include('../../../snippets/social/twitter/5') %>
+<%= include('../../../snippets/social/twitter/6') %>
+<%= include('../../../snippets/social/twitter/7') %>
+<%= include('../../../snippets/social/twitter/8') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/vimeo.md b/articles/connections/social/vimeo.md
new file mode 100644
index 0000000000..abd1f9bc9a
--- /dev/null
+++ b/articles/connections/social/vimeo.md
@@ -0,0 +1,25 @@
+---
+title: Connect Apps to Vimeo
+connection: Vimeo
+image: /media/connections/vimeo.png
+seo_alias: vimeo
+description: Learn how to add login functionality to your app with Vimeo. You will need to obtain a Client Id and Client Secret for Vimeo.
+toc: true
+public: true
+index: 6
+topics:
+ - connections
+ - social
+ - vimeo
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
+---
+<%= include('../../../snippets/social/vimeo/0') %>
+<%= include('../../../snippets/social/vimeo/1') %>
+<%= include('../../../snippets/social/vimeo/2') %>
+<%= include('../../../snippets/social/vimeo/3') %>
+<%= include('../../../snippets/social/vimeo/4') %>
+<%= include('../../../snippets/social/vimeo/5') %>
+<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/vkontakte.md b/articles/connections/social/vkontakte.md
index 2ab11d93dd..dc24590df4 100644
--- a/articles/connections/social/vkontakte.md
+++ b/articles/connections/social/vkontakte.md
@@ -1,98 +1,25 @@
---
-title: Connect your app to vKontakte
+title: Connect Apps to vKontakte
connection: vKontakte
image: /media/connections/vkontakte.png
seo_alias: vkontakte
-description: How to connect your Auth0 app to vKontakte.
+description: Learn how to add login functionality to your app with vKontakte.
toc: true
+public: true
+index: 33
+topics:
+ - connections
+ - social
+ - vkontakte
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to vKontakte
-
-To connect your Auth0 app to vKontakte, you will need to generate an `Application ID` and `Secure Key` in a vKontakte app, copy these keys into your Auth0 settings, and enable the connection.
-
-## 1. Create a new vKontakte application
-
-Login to [vKontakte Developers](https://new.vk.com/dev).
-
-Go to **My Apps** and click **Create an Application**:
-
-
-
-Select **Website** as the **Category**.
-
-Provide a name for your app.
-
-In the **Site address** field, enter the following:
-
-`https://${account.namespace}`
-
-In the **Base domain** field, enter the following:
-
-`${account.namespace}`
-
-
-
-Click **Connect Site** to create the app.
-
-You will be required to confirm your request with a code send via SMS:
-
-
-
-
-## 2. Enter your *redirect URL*
-
-Once the application is created, select **Settings** in the left nav.
-
-In the **Authorized redirect URI** field, enter the following:
-
-`https://${account.namespace}/login/callback`
-
-Click **Save**.
-
-
-
-## 3. Get your *Application ID* and *Secure Key*
-
-From the top of the same page, copy the `Application ID` and `Secure Key` for use in the next step.
-
-
-
-## 4. Enter your *Application ID* and *Secure Key* into Auth0
-
-In a separate window, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-Select **vKontakte**:
-
-
-
-Copy the `Application ID` and `Secure Key` from the **Settings** page of your app on vKontakte into the fields on this page on Auth0.
-
-Select the Permissions you want to enable.
-
-Click **SAVE**.
-
-
-
-## 5. Enable the Connection
-
-Go to the **Apps** tab of the vKontakte connection on Auth0 and select each of your existing Auth0 apps for which you want to enable this connection and click **Save**:
-
-
-
-## 6. Test the connection
-
-Close the **Settings** window to return to the **Connections > Social** section of the Auth0 dashboard.
-
-A **TRY** icon will now be displayed next to the vKontakte logo:
-
-
-
-Click **TRY**.
-
-If you have configured everything correctly, you will see the **It works!!!** page:
-
-
-
+<%= include('../../../snippets/social/vkontakte/0') %>
+<%= include('../../../snippets/social/vkontakte/1') %>
+<%= include('../../../snippets/social/vkontakte/2') %>
+<%= include('../../../snippets/social/vkontakte/3') %>
+<%= include('../../../snippets/social/vkontakte/4') %>
+<%= include('../../../snippets/social/vkontakte/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/weibo.md b/articles/connections/social/weibo.md
index 9aa33158b6..da8a641a45 100644
--- a/articles/connections/social/weibo.md
+++ b/articles/connections/social/weibo.md
@@ -1,78 +1,25 @@
---
-title: Connect your app to Weibo
+title: Connect Apps to Weibo
+description: Learn how to add login functionality to your app with Weibo.
connection: Weibo
image: /media/connections/weibo.png
seo_alias: weibo
-description: How to obtain an App ID and App Secret for Weibo.
+public: true
+index: 34
toc: true
+topics:
+ - connections
+ - social
+ - weibo
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Weibo
-
-To configure a Weibo connection you will need to register Auth0 on the [Weibo App portal](http://open.weibo.com/apps).
-
-## 1. Add a new Application
-
-First log in into your [Weibo portal](http://open.weibo.com/apps), once you have logged in go to the [Development page](http://open.weibo.com/development) and click on the orange button.
-
-
-
-This will bring up options for which type of application you wish to create. Select the web application option which should be third from the left.
-
-
-
-In the first field, enter the name for your application. Make sure **Web Application** (the third option 网页应用) is selected for the application type. The check box agrees to the terms.
-
-
-
-## 2. Enter your callback URLs
-
-Then you will be brought to your application information page. Click on advanced (高级信息) options from the left sidebar.
-
-
-
-Under OAuth2.0 授权设置 enter `https://${account.namespace}/login/callback` as the callback urls. Then click on the green button.
-
-
-
-## 3. Get your **App Key** and **App Secret**
-
-Return to the basic information page (基本信息) for your application by clicking on the top option under the gear icon for Application Information.
-
-
-
-This page will contain your **App Key** and **App Secret**, to be used in the next step.
-
-
-
-## 4. Setup the Connection in Auth0
-
-In a seperate tab or page, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-Click on the **Weibo** connection.
-
-Enter your **App Key** and **App Secret** from Weibo, select your **Attributes** and **Permissions** then click **SAVE**.
-
-
-
-Next click on the **Applications** tab next to **Settings** and enable which of your applications will be able to use this connection.
-
-
-
-When finished, click **SAVE**.
-
-## 5. Test the Connection
-
-On the [Connections > Social](${manage_url}/#/connections/social) page of the Auth0 dashboard you should now see a **TRY** button with the Weibo connection.
-
-
-
-Click on this to test the new connection. This should bring up a confirmation page for the connection:
-
-
-
-If accepted, you should be able to see the **It Works!** confirmation page that your connection has been configured correctly.
-
+<%= include('../../../snippets/social/weibo/0') %>
+<%= include('../../../snippets/social/weibo/1') %>
+<%= include('../../../snippets/social/weibo/2') %>
+<%= include('../../../snippets/social/weibo/3') %>
+<%= include('../../../snippets/social/weibo/4') %>
+<%= include('../../../snippets/social/weibo/5') %>
<%= include('../_quickstart-links.md') %>
-
-
diff --git a/articles/connections/social/wordpress.md b/articles/connections/social/wordpress.md
index 37730783f2..3a74755bca 100644
--- a/articles/connections/social/wordpress.md
+++ b/articles/connections/social/wordpress.md
@@ -1,81 +1,25 @@
---
-title: Connect your app to WordPress
+title: Connect Apps to WordPress
+description: Learn how to add login functionality to your app with WordPress. You will need to obtain a Client Id and Client Secret for WordPress.
connection: WordPress
image: /media/connections/wordpress.png
seo_alias: wordpress
-index: 11
-description: How to obtain a Client Id and Client Secret for WordPress
+public: true
+index: 35
toc: true
+topics:
+ - connections
+ - social
+ - wordpress
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your App to WordPress
-
-To configure WordPress OAuth2 connections, you will need to register Auth0 with the [WordPress Developer Portal](http://developer.wordpress.com/).
-
-## 1. Log in to the Developer Portal
-
-Go to the [WordPress Developer Portal](http://developer.wordpress.com/), and log in with your WordPress credentials. Select **My Apps** from the top menu.
-
-
-
-## 2. Provide Your Auth0 Application Information.
-
-If you have not already registered your application with Wordpress, click **Create New Application**:
-
-
-
-Complete all the fields on the **Create an Application** screen.
-
-
-
-|**Field**|**Description**|
-|-|-|
-|**Name** | The name of your application|
-|**Description** | The description of your application|
-|**Website URL** | The URL to an informational home page about your application|
-|**Redirect URL** | Enter `https://${account.namespace}/login/callback` in this field|
-|**Javascript Origins** | (optional) Whitelist URLs to prevent unauthenticated GET requests|
-|**Verification Question** | To confirm you are an actual user performing the request|
-|**Type** | Select **Web** as the client type|
-
-After completing the fields, click on the **Create** button.
-
-Then (or if you have previously registered your application) you will see your application listed on your dashboard landing page.
-
-
-
-## 3. Get your Client ID and Client Secret
-
-On the **My Applications** dashboard page, click **Manage Application**. Under the **OAuth Information** you will see your **Client ID** and **Client Secret**.
-
-
-
-In a seperate tab or window, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-Click on the box with the **WordPress** logo.
-
-This will bring up the WordPress connection settings. Copy the **Client ID** and **Client Secret** from your WordPress application.
-
-
-
-Click **SAVE**. Then click the **Clients** tab and select the applications you wish to enable this connection.
-
-
-
-Click **SAVE** when finished.
-
-## 4. Test the connection
-
-In the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard a **TRY** icon will now be displayed next to the WordPress logo:
-
-
-
-Click **TRY**.
-
-The WordPress access page will appear.
-
-
-
-Click **Approve** and if configured correctly, you will see the **It works!!!** page:
-
+<%= include('../../../snippets/social/wordpress/0') %>
+<%= include('../../../snippets/social/wordpress/1') %>
+<%= include('../../../snippets/social/wordpress/2') %>
+<%= include('../../../snippets/social/wordpress/3') %>
+<%= include('../../../snippets/social/wordpress/4') %>
+<%= include('../../../snippets/social/wordpress/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connections/social/yahoo.md b/articles/connections/social/yahoo.md
index 71b88c756b..ea9a93396c 100644
--- a/articles/connections/social/yahoo.md
+++ b/articles/connections/social/yahoo.md
@@ -1,71 +1,25 @@
---
-title: Connect your app to Yahoo!
+title: Connect Apps to Yahoo
+description: Learn how to add login functionality to your app with Yahoo. You will need to obtain a Consumer Key and Consumer Secret for Yahoo.
connection: Yahoo!
image: /media/connections/yahoo.png
seo_alias: yahoo
-index: 15
-description: How to obtain a Consumer Key and Consumer Secret for Yahoo!
+public: true
+index: 36
toc: true
+topics:
+ - connections
+ - social
+ - yahoo
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Yahoo!
-
-These steps will guide you through how to create an application with Yahoo! and how to add it as a social connection in the Auth0 Dashboard.
-
-## 1. Add a New Application
-
-To begin, you need a Yahoo user ID. If you don’t have one ([login.yahoo.com](https://login.yahoo.com) or [admanager.yahoo.com](https://admanager.yahoo.com)), you need to create one.
-
-Then, go to [Yahoo Developer Apps](https://developer.yahoo.com/apps/) and click on the **Create an App** button.
-
-
-
-Create an **Application Name** and select **Web Application** as the **Application Type**.
-
-
-
-In the **Callback Domain** field enter:
-
-`https://${account.namespace}`
-
-For the **API Permissions** make sure to select at least one user data API:
-
-
-
-## 2. Get your **Client Key** and **Client Secret**
-
-Once the application is created you will see a **Client ID** (Consumer Key) and **Client Secret** (Consumer Secret). Copy these values as you will use them to set up the connection in Auth0.
-
-
-
-## 3. Set up the Connection in Auth0
-
-In a seperate tab or page, go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-Click on the **Yahoo!** connection.
-
-Enter your **Client Key** and **Client Secret** from Yahoo! then click **SAVE**.
-
-
-
-Next click on the **Applications** tab next to **Settings** and enable which of your applications will be able to use this connection.
-
-
-
-When finished, click **SAVE**.
-
-## 4. Test the Connection
-
-On the [Connections > Social](${manage_url}/#/connections/social) page of the Auth0 dashboard you should now see a **TRY** button with the Yahoo! connection.
-
-
-
-Click on this to test the new connection. This should bring up a confirmation page for the connection:
-
-
-
-If accepted, you should be able to see the **It Works!** confirmation page that your connection has been configured correctly.
-
+<%= include('../../../snippets/social/yahoo/0') %>
+<%= include('../../../snippets/social/yahoo/1') %>
+<%= include('../../../snippets/social/yahoo/2') %>
+<%= include('../../../snippets/social/yahoo/3') %>
+<%= include('../../../snippets/social/yahoo/4') %>
+<%= include('../../../snippets/social/yahoo/5') %>
<%= include('../_quickstart-links.md') %>
-
-
diff --git a/articles/connections/social/yammer.md b/articles/connections/social/yammer.md
index 79c7801430..8a5242f8ff 100644
--- a/articles/connections/social/yammer.md
+++ b/articles/connections/social/yammer.md
@@ -1,71 +1,25 @@
---
-title: Connect your app to Yammer
+title: Connect Apps to Yammer
+description: How to obtain the credentials required to configure your Auth0 connection to Yammer.
connection: Yammer
image: /media/connections/yammer.png
-description: How to obtain the credentials required to configure your Auth0 connection to Yammer.
seo_alias: yammer
+public: true
+index: 37
toc: true
+topics:
+ - connections
+ - social
+ - yammer
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Yammer
-
-To configure Yammer for OAuth connections, you will need to register your Auth0 namespace on the Yammer Developer Center.
-
-## 1. Login to Yammer Developer Center
-
-Go to [Yammer Developer Center](https://developer.yammer.com/) and login with your account. Click on **Apps** in the top menu:
-
-
-
-Click on **Register an App**:
-
-
-
-Then click **Register New App**:
-
-
-
-## 2. Name your application
-
-Name your app and complete the form.
-For the **Redirect URI**, enter `https://${account.namespace}/login/callback`.
-Click **Continue**.
-
-
-
-## 3. Get your *Client ID* and *Client Secret*
-
-Once your app is created, your `Client ID` and `Client Secret` will be displayed:
-
-
-
-## 4. Copy the *Client ID* and *Client Secret* into Auth0
-
-Go to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard and select **Yammer**.
-Copy the `Client ID` and `Client Secret` from the **Basic Info** page of your app on Yammer into the fields on this page on Auth0.
-Click **Save**:
-
-
-
-## 5. Test your app
-
-Go back to the [Connections > Social](${manage_url}/#/connections/social) section of the Auth0 dashboard.
-
-If you have configured your app correctly, you will see a Try icon next to the Yammer logo.
-Toggle on the switch to enable Yammer authentication:
-
-
-
-Select the apps you would like to use Yammer authentication with.
-Click **Continue**:
-
-
-
-Now you can test your new app by clicking **Try**:
-
-
-
-
-
+<%= include('../../../snippets/social/yammer/0') %>
+<%= include('../../../snippets/social/yammer/1') %>
+<%= include('../../../snippets/social/yammer/2') %>
+<%= include('../../../snippets/social/yammer/3') %>
+<%= include('../../../snippets/social/yammer/4') %>
+<%= include('../../../snippets/social/yammer/5') %>
<%= include('../_quickstart-links.md') %>
-
diff --git a/articles/connections/social/yandex.md b/articles/connections/social/yandex.md
index db2e647889..39e858e5ef 100644
--- a/articles/connections/social/yandex.md
+++ b/articles/connections/social/yandex.md
@@ -1,43 +1,25 @@
---
-title: Connect your app to Yandex
+title: Connect Apps to Yandex
+description: How to obtain an Application ID and Application Password for Yandex.
connection: Yandex
image: /media/connections/yandex.png
seo_alias: yandex
-description: How to obtain an Application ID and Application Password for Yandex.
+public: true
+index: 38
toc: true
+topics:
+ - connections
+ - social
+ - yandex
+contentType: how-to
+useCase:
+ - customize-connections
+ - add-idp
---
-
-# Connect your app to Yandex
-
-To configure an Yandex connection you will need to register your Auth0 instance as a Yandex application.
-
-## 1. Create a new Application in Yandex:
-
-Log in into Yandex and [create a new app](https://oauth.yandex.ru/client/new):
-
-::: note
-Complete instructions are available [here](http://api.yandex.ru/oauth/doc/dg/tasks/register-client.xml)
-:::
-
-
-## 2. Register a new application
-
-Complete the form:
-
-
-
-The callback address for your app should be:
-
- https://${account.namespace}/login/callback
-
-
-Notice that `scopes` in Yandex are defined in this screen. Select what kind of information you are requesting for your app.
-
-
-## 3. Get your Application ID and Application Password
-
-Once the application is registered, enter your new `Application ID` and `Application Password` into the connection settings in Auth0.
-
-
-
+<%= include('../../../snippets/social/yandex/0') %>
+<%= include('../../../snippets/social/yandex/1') %>
+<%= include('../../../snippets/social/yandex/2') %>
+<%= include('../../../snippets/social/yandex/3') %>
+<%= include('../../../snippets/social/yandex/4') %>
+<%= include('../../../snippets/social/yandex/5') %>
<%= include('../_quickstart-links.md') %>
diff --git a/articles/connector/client-certificates.md b/articles/connector/client-certificates.md
index aa64b83295..ffce9fcd95 100644
--- a/articles/connector/client-certificates.md
+++ b/articles/connector/client-certificates.md
@@ -1,27 +1,40 @@
---
description: How to setup authentication using client certificates.
+topics:
+ - connector
+ - ad/ldap
+ - client-certificates
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Client Certificate Support
-In addition to Kerberos, the AD/LDAP Connector also allows users to authenticate using __client certificates__. With this, users authenticate with a certificate installed on their machine or device.
+In addition to Kerberos, the [AD/LDAP Connector](/connector) also allows users to authenticate using **client certificates**. With this, users authenticate with a certificate installed on their machine or device.
-## Configuration
+## Configure the AD/LDAP connection
-To activate Client Certificates on an LDAP connection, simply enable the option in the dashboard:
+To activate client certificates on an AD/LDAP connection:
+
+1. Go to [Connections > Enterprise](${manage_url}/#/connections/enterprise) and select your AD/LDAP connection.
+2. Toggle the **Use client SSL certificate authentication** option in the settings.
+3. Provide IP address ranges in the **IP Ranges** field. Only users coming from the given IP ranges are prompted to authenticate using client certificates. Users from different IP ranges are prompted to login with the username/password login form.

-::: note
-Note that you'll also need to configure the IP Ranges. Only users coming from these IP Ranges will be prompted to authenticate using Client Certificates. Users that originate from different IP Ranges will be presented with the traditional username/password login form.
-:::
+## Configure the certificates
-Once this has been configured in Auth0 you'll need to configure the certificates in the AD/LDAP Connector. Supporting Client Certificates will require the following:
+Once the AD/LDAP connection has been configured in Auth0, you'll need to configure the certificates in the AD/LDAP Connector. Supporting client certificates will require the following:
1. An __SSL certificate__ for the **Front Facing Url**, because the interaction between the end user and the Connector will need to happen over HTTPS.
2. One or more __CA certificates__.
3. A __Client Certificate__ signed by the CA for each user that needs to authenticate using Client Certificates.
+Before uploading certificates to the AD/LDAP connector, convert X509 certificates to Base64. To do this you can use a simple online tool like [this one](https://www.base64decode.org/), or you can use [Certutil.exe](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/certutil#BKMK_encode) on Windows Server.
+
The SSL certificate and the CA certificate can be uploaded in the AD/LDAP Connector:

diff --git a/articles/connector/considerations-non-ad.md b/articles/connector/considerations-non-ad.md
index d43ebad0a1..a70e29d7fc 100644
--- a/articles/connector/considerations-non-ad.md
+++ b/articles/connector/considerations-non-ad.md
@@ -1,5 +1,13 @@
---
description: How to configure the Connector for OpenLDAP and other directories that are not AD.
+topics:
+ - connector
+ - openldap
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Considerations for OpenLDAP and non-AD directories
diff --git a/articles/connector/high-availability.md b/articles/connector/high-availability.md
index 57330e8236..cfc2cb90ea 100644
--- a/articles/connector/high-availability.md
+++ b/articles/connector/high-availability.md
@@ -1,40 +1,59 @@
---
-description: How to install multiple instances of the connectory for higher availability.
+description: How to install multiple instances of the connector for higher availability.
+topics:
+ - connector
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
+# Deploy the Connector in a High Availability (HA) Environment
-# High availability
+The connector is a critical component. Therefore we recommend a highly available deployment with redundancy (that is, installing multiple instances of it).
-The connector is a very important component, therefore we recommend a highly available deployment through redundancy: installing multiple instances of it.
+## How high availability helps
-If one of the instances fails either because of a network issue or hardware issue, Auth0 will redirect the login transactions to the other connector.
+Each instance of the high-availability cluster will be always up and running and connected to Auth0. Auth0 will send login transactions and other requests to any of the available connectors.
-Having a highly available deployment also allows updating the connector with zero downtime.
+If one of the instances fails because of a network or a hardware issue, Auth0 will redirect the login transactions to the other connector.
-## Instructions for Windows
+Having a highly available deployment also allows you to update the connector with zero downtime.
-1. Install the connector as explained [here](/connector/install).
-2. Make sure all steps are complete and the connector is up and running.
-3. Navigate to the Admin Console and export the configuration: [http://localhost:8357/#export](http://localhost:8357/#export)
-4. Install the connector on a second server following the same instructions as above.
-5. When prompted for the __Ticket URL__, go to the __Import / Export__ tab and import the configuration there.
+## Overview of the multiple-connector installation process
-
+Installing multiple instances of the connector in a high-availability deployment involves:
-## Instructions for Linux
+- **A regular first-time installation.** This is where you provide the ticket URL that links the connector to a specific connection in your Auth0 tenant and other configuration parameters.
+- **Making copies of the original installation and populating it to other servers.** This ensures that the same configuration and certificates securing communications are used in each instance.
-1. Install the connector as explained [here](/connector/install).
-2. Make sure all steps are complete and the connector is up and running.
-3. Copy **config.json**, **lib/profileMapper.js** and everything under the **certs** folder from:
- - Windows: `C:\Program Files (x86)\Auth0\AD LDAP Connector\`
- - Linux: `/opt/auth0/ad-ldap`
+::: note
+The following instructions are for Windows/Linux users only.
+:::
-4. Install the connector on a second server following the same instructions as above. When prompted for the __Ticket URL__ close the dialog.
-5. On the **second server**, overwrite the default files, `config.json`, `lib/profileMapper.js` and the files in `certs` directory, with the versions of those files from the **first server** that were copied/saved in step 3 above.
-6. Restart the service on the second server.
+### Step 1. Setting up your first server
-## Kerberos or certificate based authentication considerations
+1. [Install the connector](/connector/install) on the first server.
+1. Once the connector is installed, configured, and working correctly on your first server, copy **config.json**, **lib/profileMapper.js** and everything in the **certs** folder from:
+ - *For Windows users*: **C:\Program Files (x86)\Auth0\AD LDAP Connector\**
+ - *For Linux users*: **/opt/auth0/ad-ldap**
+1. Back up the files copied from the step above, since you will use them to configure the additional instances of the connector on your other server(s).
-If you enable [Kerberos](/connector/kerberos) or [application certificates](/connector/application-certificates) based authentication in your AD/LDAP connections, users will contact the connector directly, instead of going through the Auth0 server. In these scenarios where multiple connector instances exist, we recommend fronting them with a network load balancer. The `SERVER_URL` parameter can be used to publish the public location where the connector will be listening to incoming requests.
+### Step 2. Setting up additional servers
-This URL should be then mapped in the network load balancer to all internal instances of the deployed connectors. No special distribution policy is required (for example, uniform round-robin, with no sticky sessions, should work).
+1. [Install the connector](/connector/install) on the additional servers. **Do not configure the connector on the additional server yet.**
+2. Replace the configuration files for your additional servers **with the files you saved from configuring your first server.** When done, you'll over overwritten the additional servers' **config.json** and **lib/profileMapper.js** files, as well as the **./certs/** folder.
+3. Restart the **Auth0 ADLDAP** and **Auth0 ADLDAP** Admin Windows Services on the secondary servers.
+4. Open the troubleshooting screen (accessible at **http://localhost:8357/#troubleshoot**) and run the troubleshooting test. Make sure all tests pass.
+### Verify your connection
+
+Once you've completed the installation process, you verify your installation using the **Connections** section of the Auth0 Dashboard. The AD Connection will have a green dot next to its name to indicate that it can use the connection successfully.
+
+## Kerberos or certificate-based authentication considerations
+
+If you enable [Kerberos](/connector/kerberos) or [client certificates](/connector/client-certificates) based authentication in your AD/LDAP connections, users will contact the connector directly instead of going through the Auth0 server.
+
+In scenarios where multiple connector instances exist, we recommend fronting them with a network load balancer. The `SERVER_URL` parameter can be used to publish the public location where the connector will be listening to incoming requests.
+
+The `SERVER_URL` should be then mapped in the network load balancer to all internal instances of the deployed connectors. No special distribution policy is required (e.g., uniform round-robin, with no sticky sessions, works).
diff --git a/articles/connector/index.md b/articles/connector/index.md
index f748b8bbf7..52f5506f2d 100644
--- a/articles/connector/index.md
+++ b/articles/connector/index.md
@@ -3,6 +3,16 @@ url: /connector
classes: topic-page
title: Active Directory/LDAP Connector
description: Explains what the connector is and links to resources to learn more about it.
+topics:
+ - connector
+contentType:
+ - index
+ - concept
+ - how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
diff --git a/articles/connector/install-other-platforms.md b/articles/connector/install-other-platforms.md
index 5772f213d8..d97c116c95 100644
--- a/articles/connector/install-other-platforms.md
+++ b/articles/connector/install-other-platforms.md
@@ -1,5 +1,12 @@
---
description: A guide on installing the AD/LDAP Connector on different platforms.
+topics:
+ - connector
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Install the AD/LDAP Connector on Non-Microsoft Platforms
@@ -82,5 +89,5 @@ For most platforms, you will need to run the required commands with root privile
7. Run `node admin/server.js` to access the admin UI -- the admin UI will be running and available on `http://localhost:8357`.
::: note
-If you get an `Invalid Ticket` message when configuring the Connector for the first time, the most likely cause is a network issue (for example, you have the Connector running behind a proxy). Try troubleshooting by connecting to `https://YOUR_TENANT.auth0.com/testall` with a browser other than Internet Explorer.
+If you get an `Invalid Ticket` message when configuring the Connector for the first time, the most likely cause is a network issue (for example, you have the Connector running behind a proxy).
:::
diff --git a/articles/connector/install.md b/articles/connector/install.md
index 67bd30b741..87943bb0b8 100644
--- a/articles/connector/install.md
+++ b/articles/connector/install.md
@@ -1,5 +1,12 @@
---
description: Directions on how to install the Connector with Windows.
+topics:
+ - connector
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Installing the Connector on Windows
diff --git a/articles/connector/kerberos.md b/articles/connector/kerberos.md
index b09501cf9d..06a12a5e0d 100644
--- a/articles/connector/kerberos.md
+++ b/articles/connector/kerberos.md
@@ -1,6 +1,17 @@
---
description: Explains AD/LDAP Federation Support with Auth0, how to configure it, the flow, and auto-login with Lock.
toc: true
+topics:
+ - connector
+ - ad/ldap
+ - kerberos
+contentType:
+ - how-to
+ - concept
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Federating with Active Directory through the AD/LDAP Connector
@@ -24,11 +35,17 @@ We recommend restarting the Windows Service that hosts the AD Connector every ti
When Auth0 is running in the cloud, it won't be able to see your user's internal IP address. In that case you'd configure the public facing/WAN IP address(es) of your company.
+### Auto-detected range for Kerberos
+
+When Kerberos authentication is enabled, the visible IP address of the server where the AD Connector is running is implicitly added to the network IP range.
+
+This means that if a user's requests originate from the same visible IP address as that of the AD Connector, then Kerberos authentication will be attempted.
+
## Flow
Depending on the location of the user the authentication flow will be different when IP ranges are set. Let's take Fabrikam as an example. Since Fabrikam uses the SaaS version of Auth0 they configured their Public IP Address (`24.12.34.56/32`) in the connection.
-Users connecting from within the building will all originate from `24.12.34.56` (as configured on the connection). When they authenticate, the users can follow the AD/LDAP native flow and have a seamless SSO experience.
+Users connecting from within the building will all originate from `24.12.34.56` (as configured on the connection). When they authenticate, the users can follow the AD/LDAP native flow and have a seamless Single Sign-on (SSO) experience.
::: note
For this to work, the network must allow the users to connect to the AD/LDAP Connector on the port configured in the `config.json` file. In [highly available](/connector/high-availability) deployments of the connector, the address users will be connecting to is the network load balancer in front of all connectors instances.
@@ -43,44 +60,79 @@ On the other hand, when users are not in the corporate network (for example, at
## Auto-login with Lock
::: warning
-Detecting IP ranges in an Active Directory/LDAP connection and using those ranges with Lock to allow integrated Windows Authentication is a feature which works in Lock 10 but is disabled in Lock 11.
+Detecting IP ranges in an Active Directory/LDAP connection and using those ranges with Lock to allow integrated Windows Authentication is a feature that works in Lock 10, but can only be used in Lock 11 in Universal Login scenarios. This feature is *disabled* in Lock 11 when Lock 11 is used in Embedded Login scenarios.
:::
-When an application is using Lock within the Login Page hosted by Auth0 (typically used for SAML/WS-Federation protocols and SSO Integrations), there will be a button which allows users to authenticate using "Windows Authentication".
+When an application is using Lock 10 or 11 within the Login Page hosted by Auth0 (typically used for SAML/WS-Federation protocols and Single Sign-on (SSO) Integrations), there will be a button which allows users to authenticate using "Windows Authentication".
In some cases the requirement could be to automatically sign in the user if Kerberos is possible (based on the IP-address of the end user). The following changes can be added to the Auth0 Login Page to automatically sign in the user if Kerberos is possible:
-```js
-/*
- * Helper to get a querystring value.
- */
-function getParameterByName( name ){
- name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
- var regexS = "[\\?&]"+name+"=([^]*)";
- var regex = new RegExp( regexS );
- var results = regex.exec( window.location.href );
- if( results == null )
- return "";
- else
- return decodeURIComponent(results[1].replace(/\+/g, " "));
-}
-
-/*
- * Verify if Kerberos is possible (based on the IP address).
- * If it is, try to authenticate the user.
- */
-lock.$auth0.getSSOData(true, function(err, data) {
- if (!err) {
+```html
+
+
+
+
+
+```
+
+## Skipping Kerberos at runtime
+
+You can prevent Kerberos from being used, even if the user is logging in from an IP address within the range configured in the connection's settings, by passing `rememberLastLogin: false` to `lock.show()`
+
+
+```js
+
+function useKerberos() {
+ // return true to use Kerberos, false to bypass
+};
+
+lock.show({rememberLastLogin: useKerberos()});
```
## Troubleshooting
@@ -89,7 +141,7 @@ To enable verbose logging of Kerberos requests, add a system level environment v
## Firefox support for Kerberos
-By default, [Firefox](https://www.mozilla.org/firefox) [rejects all "negociate" requests required to authenticate users with Kerberos](https://developer.mozilla.org/en-US/docs/Mozilla/Integrated_authentication). If you wish to use Firefox with Kerberos, you need to whitelist the server where the connector is installed. To do that:
+By default, [Firefox](https://www.mozilla.org/firefox) [rejects all "negotiate" requests required to authenticate users with Kerberos](https://developer.mozilla.org/en-US/docs/Mozilla/Integrated_authentication). If you wish to use Firefox with Kerberos, you need to whitelist the server where the connector is installed. To do that:
* Open a Firefox tab and type `about:config` in the address bar.
* Dismiss any warning message, and in the search box type `negotiate`.
diff --git a/articles/connector/modify.md b/articles/connector/modify.md
index b94bcc30e9..c4b4a16f84 100644
--- a/articles/connector/modify.md
+++ b/articles/connector/modify.md
@@ -1,5 +1,12 @@
---
description: How to modify AD/LDAP Connector settings in the console, Profile Mapper, or config file.
+topics:
+ - connector
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Modify the AD/LDAP Connector Settings
@@ -66,42 +73,49 @@ Internet connectivity is required for an update to work.
## Configuration file
-The `config.json` file is the AD/LDAP Connector's main configuration file. It can be edited to make advanced changes that are not available via the AD/LDAP **Connector Admin Console**. The file is located in the install directory for the AD/LDAP Connector. The following settings are supported in this file:
-
- - `AD_HUB`: The Auth0 endpoint to which the connector will connect. This value is maintained by the connector.
- - `CA_CERT`: An authority certificate or array of authority certificates to check the remote host against.
- - `CLIENT_CERT_AUTH`: Specifies if **Client Certificate Authentication** is enabled or not. This value is configured in Auth0 and maintained by the connector.
- - `CONNECTION`: The name of the connection in Auth0 which is linked to this instance of the connector. This value is maintained by the connector.
- - `CONNECTIONS_API_V2_KEY`: A Management APIv2 token which is used to call the [Get a connection](/api/management/v2#!/Connections/get_connections_by_id) endpoint. Set this when you need to troubleshoot the connector. This will compare the local certificate to the one configured in Auth0 and detect a possible mismatch.
- - `FIREWALL_RULE_CREATED`: Will be set to `true` once the Firewall rule has been created for the Kerberos Server (only when Kerberos is enabled).
- - `GROUPS`: Include the user's groups when enriching the profile. Default: `true`.
- - `GROUP_PROPERTY`: The attribute of the group object that will be used when adding the groups to a user. Default: `cn`.
- - `GROUPS_CACHE_SECONDS`: Total time in seconds to cache a user's groups. Default: 600 seconds.
- - `GROUPS_TIMEOUT_SECONDS`: The timeout in seconds for searching all groups a user belongs to. Default: 20 seconds.
- - `HTTP_PROXY`: The URL of a proxy server if one is required to connect from the AD/LDAP Connector to Auth0.
- - `KERBEROS_AUTH`: Specifies if **Kerberos Authentication** is enabled or not. This value is configured in Auth0 and maintained by the connector.
- - `LAST_SENT_THUMBPRINT`: Thumbprint of the last certificate which was sent to Auth0.
- - `LDAP_BASE`: Defines the location in the directory from which the LDAP search begins. Eg: `DC=fabrikam,DC=local`.
- - `LDAP_BASE_GROUPS`: Defines the location in the directory from wich the LDAP search for groups begins.
- - `LDAP_BIND_PASSWORD`: The password of the LDAP user. This setting will automatically be removed after the connector has been initialized.
- - `LDAP_BIND_CREDENTIALS`: The encrypted password of the LDAP user. This setting will automatically be added after the connector has been initialized.
- - `LDAP_BIND_USER`: The user for which we will bind a connection to LDAP.
- - `LDAP_HEARTBEAT_SECONDS`: The keep-alive in seconds to keep the LDAP connection open.
- - `LDAP_SEARCH_ALL_QUERY`: The LDAP query used to list all users in the LDAP store. Default: `(objectCategory=person)`.
- - `LDAP_SEARCH_GROUPS`: The LDAP query used to find groups in the LDAP store. Default: `(member:1.2.840.113556.1.4.1941:={0})`.
- - `LDAP_SEARCH_QUERY`: The LDAP query used to find users in the LDAP store. Default: `(&(objectCategory=person)(anr={0}))`.
- - `LDAP_USER_BY_NAME`: The LDAP query used to find the user during authentication. This setting allows you to specify which attribute will be considered as the user's username, like the common name, the sAMAccountName, UPN, ... Default: `(sAMAccountName={0})`.
- - `LDAP_URL`: The LDAP connection string, eg: `ldap://fabrikam-dc.fabrikam.local`.
- - `PORT`: The port on which the server will run when Kerberos or Client Certificate Authentication is enabled.
- - `PROVISIONING_TICKET`: The Auth0 provisioning ticket used to communicate with Auth0.
- - `REALM`: The Auth0 realm, eg: `urn:auth0:fabrikam`. This value is maintained by the connector.
- - `SERVER_URL`: The default connector URL will be `server-name:port`, but this setting allows you to overwrite this (eg: `connector.mycompany.com`).
- - `SESSION_SECRET`: The session secret used to encrypt the session cookie.
- - `SITE_NAME`: When Client Certificate Authentication is enabled, but not possible the AD Connector will show a fallback login page. This setting allows you to specify the title that will show on top of the page. Default: name of the AD connection.
- - `SSL_KEY_PASSWORD`: The password for the SSL certificate.
- - `SSL_PFX`: Base64 encoded certificate to use for SSL.
- - `TENANT_SIGNING_KEY`: Your Auth0 tenant used to verify JWTs (eg: when a user authenticates, we verify that the authentication request comes from Auth0 using a JWT).
- - `WSFED_ISSUER`: The issuer being set in the WS-Federation responses. If a connection is configured with email domains, the first email domain configured in Auth0 will be used as issuer. Default: `urn:auth0`.
+The `config.json` file is the AD/LDAP Connector's main configuration file. You can this to make advanced changes that are not available via the AD/LDAP **Connector Admin Console**. The file is located in the install directory for the AD/LDAP Connector, which (for Windows) is usually found at `C:\Program Files (x86)\Auth0\AD LDAP Connector`. The following settings are supported in this file:
+
+| Setting | Description | Default |
+|---------------|-------------|----------|
+| `AD_HUB` | The Auth0 endpoint to which the connector will connect. This value is maintained by the connector. | |
+| `CA_CERT` | An authority certificate or array of authority certificates to check the remote host against. | |
+| `CLIENT_CERT_AUTH` | Specifies if **Client Certificate Authentication** is enabled or not. This value is configured in Auth0 and maintained by the connector. | |
+| `CONNECTION` | The name of the connection in Auth0 which is linked to this instance of the connector. This value is maintained by the connector. | |
+| `CONNECTIONS_API_V2_KEY` | A Management APIv2 token used to call the [Get a connection](/api/management/v2#!/Connections/get_connections_by_id) endpoint. Set this when you need to troubleshoot the connector. This compares the local certificate to the one configured in Auth0 and detects a possible mismatch. | |
+| `FIREWALL_RULE_CREATED` | Set to `true` once the Firewall rule has been created for the Kerberos Server (only when Kerberos is enabled). | |
+| `GROUPS` | Include the user's groups when enriching the profile. | `true` |
+| `GROUP_PROPERTY` | The attribute of the group object used when adding the groups to a user. | `cn` |
+| `GROUPS_CACHE_SECONDS` | Total time in seconds to cache a user's groups. | 600 seconds. |
+| `GROUPS_TIMEOUT_SECONDS` | The timeout in seconds for searching all groups a user belongs to. | 20 seconds |
+| `HTTP_PROXY` | The proxy server URL if one is required to connect from the AD/LDAP Connector to Auth0.
+| `KERBEROS_AUTH` | Set if **Kerberos Authentication** is enabled or not. This value is configured in Auth0 and maintained by the connector. | |
+| `LAST_SENT_THUMBPRINT` | Thumbprint of the last certificate which was sent to Auth0. | |
+| `LDAP_BASE` | Defines the location in the directory where the LDAP search begins. For example: `DC=fabrikam,DC=local`. | |
+| `LDAP_BASE_GROUPS` | Defines the location in the directory where the LDAP groups search begins. | |
+| `LDAP_BIND_PASSWORD` | The password of the LDAP user. This setting is automatically removed after the connector initializes. | |
+| `LDAP_BIND_CREDENTIALS` | The encrypted password of the LDAP user. This setting is automatically added after the connector initializes. | |
+| `LDAP_BIND_USER` | The user for binding a connection to LDAP. | |
+| `LDAP_HEARTBEAT_SECONDS` | Time in seconds to keep the LDAP connection open. | |
+| `LDAP_SEARCH_ALL_QUERY` | The LDAP query used to list all users in the LDAP store. | `(objectCategory=person)` |
+| `LDAP_SEARCH_GROUPS` | The LDAP query used to find groups in the LDAP store. For example: `(&(objectCategory=group)(member={0}))` | `(member:1.2.840.113556.1.4.1941:={0})` |
+| `LDAP_SEARCH_QUERY` | The LDAP query used to find users in the LDAP store. | `(&(objectCategory=person)(anr={0}))` |
+| `LDAP_USER_BY_NAME` | The LDAP query used to find the user during authentication. This setting lets you specify which attribute is considered the user's username. For example, like the common name: the sAMAccountName, UPN, et cetera. This setting also supports multiple values for an OR search, for example: `(|(sAMAccountName={0})(userPrincipalName={0}))` | `(sAMAccountName={0})` |
+| `LDAP_URL` | The LDAP connection string. For example: `ldap://fabrikam-dc.fabrikam.local`. | |
+| `PORT` | The port the server runs on when Kerberos or Client Certificate Authentication is enabled. | |
+| `PROVISIONING_TICKET` | The Auth0 provisioning ticket used to communicate with Auth0. | |
+| `REALM` | The Auth0 realm, for example: `urn:auth0:fabrikam`. This value is maintained by the connector. | |
+| `SERVER_URL` | The default connector URL will be `server-name:port`, but this setting allows you to overwrite this. For example: `connector.mycompany.com`. | |
+| `SESSION_SECRET` | The session secret used to encrypt the session cookie. | |
+| `SITE_NAME` | When Client Certificate Authentication is enabled, but not possible the AD Connector will show a fallback login page. This setting allows you to specify the title that will show on top of the page. | Name of the AD connection. |
+| `SSL_CA_PATH` | Absolute path to the base directory where the CA certificate file(s) are located. | |
+| `SSL_KEY_PASSWORD` | The password for the SSL certificate. | |
+| `SSL_PFX` | Base64 encoded certificate to use for SSL. | |
+| `TENANT_SIGNING_KEY` | Your Auth0 tenant used to verify JWTs.
+| `WSFED_ISSUER` | The issuer being set in the WS-Federation responses. If a connection is configured with email domains, the first email domain configured in Auth0 will be used as issuer. | `urn:auth0` |
+
+This file can be used to determine which tenants are using a particular connector.
+
+For more information on LDAP queries, check out [Active Directory: LDAP Syntax Filters](https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx).
## Point an AD/LDAP Connector to a new connection
diff --git a/articles/connector/overview.md b/articles/connector/overview.md
index 0961c26d6d..0e2d35042a 100644
--- a/articles/connector/overview.md
+++ b/articles/connector/overview.md
@@ -1,30 +1,50 @@
---
title: AD/LDAP Connector Overview
description: An overview of what the AD/LDAP Connector is and why it's necessary.
+topics:
+ - connector
+contentType: concept
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# AD/LDAP Connector Overview
-Auth0 [integrates with Active Directory/LDAP](/connections/enterprise/active-directory) through an **AD/LDAP Connector** installed on your network.
+Auth0 [integrates with Active Directory/LDAP](/connections/enterprise/active-directory-ldap) through an **AD/LDAP Connector** installed on your network.
-The **AD/LDAP Connector** acts as a bridge between your **Active Directory** service and the **Auth0**. This is necessary, since AD typically runs and is accessible to your internal network, while Auth0 is a cloud service (and therefore running in a different context from your AD service).
+The **AD/LDAP Connector** acts as a bridge between your **Active Directory (AD)** service and Auth0, which is required because AD typically runs and is accessible in your internal network while Auth0 is a cloud service (and therefore runs in a different context than your AD service).
+
+::: panel-warning AD/LDAP Connector and Your Customer's Servers
+The AD/LDAP Connector is designed for scenarios where your company controls the AD/LDAP server. The connector should **not** be installed on your customer's servers.
+
+For B2B scenarios where you want to allow your customer's users to access your applications using their enterprise credentials, connect to your customer's federation service (e.g., their own Auth0 service, ADFS, or any SAML identity provider) using one of the available enterprise connections.
+
+If you install an AD/LDAP connector on your customer's servers and it is connected directly to your Auth0 domain, you will have to handle the passwords of your customer's users directly. Auth0 strongly recommends against these types of deployments and does not support them.
+:::

+1. When a user authenticates with Auth0, they are redirected to the AD/LDAP Connector.
+2. The AD/LDAP Connector validates the user against against your Active Directory (AD) service.
+3. The AD/LDAP Connector sends the results of the validation back to Auth0.
+
The Connector supports authentication based on the following:
* [LDAP](/protocols/ldap)
* [Kerberos](/connector/kerberos)
-* [Application Certificates](/connector/application-certificates)
+* [Client Certificates](/connector/client-certificates)
## Cache
-By default, an AD/LDAP Connection caches user profiles and credentials to ensure optimal uptime and performance (note that Auth0 stores a *hash* of the user's password). This data is updated each time a user logs in. The cache itself is only used when connector is down or unreachable. The cached data is always stored unless caching credentials is disabled.
+By default, an AD/LDAP Connection caches user profiles and credentials (note: Auth0 stores a *hash* of the user's password) to ensure optimal uptime and performance, and updates the data each time a user logs in. The cache is only used when the connector is down or unreachable.
+
+The cached data is always stored unless you [disable caching credentials](/dashboard/guides/connections/disable-cache-ad-ldap).
-To disable credential caching at the [connection](/identityproviders) level:
-1. Go to [Dashboard > Enterprise Connections](${manage_url}/#/connections/enterprise)
-2. Click on the **Settings** icon for the **Active Directory / LDAP** connection
-3. Toggle **Disable Cache**
+::: warning
+Values in the cache are case-sensitive, which means that login attempts will only succeed if users provide the exact username that was cached.
+:::
## Notes
diff --git a/articles/connector/prerequisites.md b/articles/connector/prerequisites.md
index 3feb5cdc55..e2701a9251 100644
--- a/articles/connector/prerequisites.md
+++ b/articles/connector/prerequisites.md
@@ -1,5 +1,12 @@
---
description: Lists all the prerequisites to installing and configuring the connector.
+topics:
+ - connector
+contentType: reference
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Prerequisites
@@ -43,7 +50,7 @@ You can enable a proxy through the environment or configuration variable `HTTP_P
### LDAP
-The Connector must be installed on a server with access to the LDAP server on port **389 for ldap** or **636 for ldaps**. Before installing the Connector you should know the **LDAP Connection String** and the **Base DN** required to connect to your LDAP directory ([more infomation](/connector/install#link-to-ldap)).
+The Connector must be installed on a server with access to the LDAP server on port **389 for ldap** or **636 for ldaps**. Before installing the Connector you should know the **LDAP Connection String** and the **Base DN** required to connect to your LDAP directory ([more information](/connector/install#link-to-ldap)).
## Inbound Connectivity
diff --git a/articles/connector/scom-monitoring.md b/articles/connector/scom-monitoring.md
index 087aa7f1a3..314815c2de 100644
--- a/articles/connector/scom-monitoring.md
+++ b/articles/connector/scom-monitoring.md
@@ -1,5 +1,14 @@
---
description: How to monitor the AD/LDAP Connector with System Center Operations Manager.
+topics:
+ - connector
+ - ad/ldap
+ - scom
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Monitoring the AD/LDAP Connector with System Center Operations Manager
@@ -22,7 +31,4 @@ You can monitor the service status using System Center as you would do with any
* Select the limits of **CPU** and **Memory limits**. Eg: 10% of CPU and 200MB of RAM are good limits to trigger alerts.
-We also recommend setting up a _synthetic transaction_ to monitor end to end authentication. More information about monitoring is available [here](/monitoring).
-
-## AD/LDAP Connector Health Webtask
-[Here](https://github.com/sandrinodimattia/auth0-ldap-connector-health-webtask) is a way to monitor health of AD/LDAP connector from Auth0 perspective. This can be done in addition to monitoring from an infrastructure perspective.
+We also recommend setting up a _synthetic transaction_ to monitor end-to-end authentication. See [Monitor Auth0 Using SCOM](/monitoring/guides/monitor-using-SCOM) for more information.
diff --git a/articles/connector/test-dc.md b/articles/connector/test-dc.md
index 3c8848e02d..2380010fa6 100644
--- a/articles/connector/test-dc.md
+++ b/articles/connector/test-dc.md
@@ -1,6 +1,14 @@
---
description: How to create and test an Active Directory Domain Controller.
toc: true
+topics:
+ - connector
+ - ad/ldap
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Creating a Test Active Directory Domain Controller
@@ -82,11 +90,11 @@ You can run your VM on any cloud platform, but this guide will walk through how
## Install and Configure the AD/LDAP Connector
-1. Using the [Auth0 Management Dashboard](${manage_url}), create a new **Active Directory/LDAP** connection with the name `auth0-test-ad` by following [these steps](/connections/enterprise/active-directory).
+1. Using the [Auth0 Management Dashboard](${manage_url}), create a new **Active Directory/LDAP** connection with the name `auth0-test-ad` by following [these steps](/connections/enterprise/active-directory-ldap).
::: note
Be sure to copy the **Ticket URL** that is generated at the end of those instructions.
:::
-1. On the VM, [disable **Internet Explorer Enhanced Security Configuration**](http://blog.blksthl.com/2012/11/28/how-to-disable-ie-enhanced-security-in-windows-server-2012/).
+1. On the VM, disable **Internet Explorer Enhanced Security Configuration**.
1. Open **Internet Explorer** with the **Ticket URL** you saved in step 1.
1. Follow the instructions in the browser to download, install, and configure the **Connector**. When you are prompted for the LDAP service account, use the admin account you created for the VM:
* Username: `mycompany\ad-admin`
diff --git a/articles/connector/troubleshooting.md b/articles/connector/troubleshooting.md
index 9b02dc8a39..81dd3e05c5 100644
--- a/articles/connector/troubleshooting.md
+++ b/articles/connector/troubleshooting.md
@@ -1,9 +1,17 @@
---
-title: Troubleshooting the Active Directory/LDAP Connector
+title: Troubleshoot Active Directory/LDAP Connector
description: Common issues and troubleshooting information for the Active Directory/LDAP Connector.
toc: true
+topics:
+ - connector
+ - ad/ldap
+contentType: reference
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
-# Troubleshooting the Active Directory/LDAP Connector
+# Troubleshoot Active Directory/LDAP Connector
We do our best to support many scenarios and different configurations.
@@ -55,12 +63,10 @@ These are the most common problems:
### Clock skew
-Make sure the clock of your server is current.
-
-If the time is not correct, it will cause authentication requests to fail. This can be fixed by ensuring that the System is properly configured to use to pool a sync server via the NTP (Network Time Protocol).
+Make sure the clock of your server is current. If the time is not correct, it will cause authentication requests to fail. This can be fixed by ensuring the system is properly configured to poll a sync server via the Network Time Protocol (NTP).
::: note
-On windows environments the ntp provider is usually the same domain controller. Make sure that your Domain Controller is synchronized with some external service.
+On Windows environments the NTP provider is usually the same domain controller. Make sure that your Domain Controller is synchronized with some external service.
:::
### No connection to Active Directory
@@ -77,9 +83,9 @@ When the domain does not exist or is unreachable `nltest` will return an error m
### UNABLE_TO_VERIFY_LEAF_SIGNATURE error message
-This error applies to the AD/LDAP Connector in combination with the PSaaS Appliance.
+This error applies to the AD/LDAP Connector in combination with the Private Cloud.
-When the connector will fail to start if unable to validate the SSL certificate configured in the PSaaS Appliance. This can happen when the Root Certificate (or any Intermediate Certificates) are missing in the machine's Certificate Store (Windows). In order to solve this you should import the certificate chain in the **Local Machine > Trusted Root** certificate store on the machine where the AD/LDAP Connector is installed.
+When the connector will fail to start if unable to validate the SSL certificate configured in the Private Cloud. This can happen when the Root Certificate (or any Intermediate Certificates) are missing in the machine's Certificate Store (Windows). In order to solve this you should import the certificate chain in the **Local Machine > Trusted Root** certificate store on the machine where the AD/LDAP Connector is installed.
### Running the connector behind a proxy
@@ -143,4 +149,8 @@ In some AD/LDAP installations, user attributes synchronization takes few minutes
To avoid the requirement of an open inbound port in your servers, the Connector creates a websocket connection to an available node in Auth0's server cluster and keeps it open to listen to incoming messages from Auth0.
-Approximately once a day (though this frequency might vary under certain circumstances) each server node will terminate the connection to allow internal deployment processes to occurr. The Connector will detect the closed connection and terminate the process, allowing the service stack to restart the process, create a new connection to an available node and resume operations. To avoid any downtime, make sure you enable [the cache for the connection](/connector/overview#cache).
+Approximately once a day (though this frequency might vary under certain circumstances) each server node will terminate the connection to allow internal deployment processes to occur. The Connector will detect the closed connection and terminate the process, allowing the service stack to restart the process, create a new connection to an available node and resume operations. To avoid any downtime, make sure you enable [the cache for the connection](/connector/overview#cache).
+
+### Receive a "postUrl is required" error
+
+This is usually thrown if additional configuration for custom domains have not been made. See [the custom domains documentation](/custom-domains/additional-configuration#configure-ad-ldap-connections) for more info.
diff --git a/articles/connector/update.md b/articles/connector/update.md
index 4b8c2c0e61..f4985be888 100644
--- a/articles/connector/update.md
+++ b/articles/connector/update.md
@@ -1,5 +1,13 @@
---
description: Explains the different ways to update the AD/LDAP Connector.
+topics:
+ - connector
+ - ad/ldap
+contentType: how-to
+useCase:
+ - add-login
+ - customize-connections
+ - add-idp
---
# Updating the AD/LDAP Connector
@@ -37,7 +45,7 @@ The updater script will update the AD/LDAP Connector from the command line by ru

::: note
-The updater script uses specific PowerShell commands that are only avaible in Windows PowerShell 3.0 and higher. If you're running on Windows 2008 and Windows 2008 R2 you might need to update your [PowerShell](https://www.microsoft.com/en-us/download/details.aspx?id=34595) version first.
+The updater script uses specific PowerShell commands that are only available in Windows PowerShell 3.0 and higher. If you're running on Windows 2008 and Windows 2008 R2 you might need to update your [PowerShell](https://www.microsoft.com/en-us/download/details.aspx?id=34595) version first.
:::
## Updating manually (Windows/Linux)
diff --git a/articles/cross-origin-authentication/fingerprinting.md b/articles/cross-origin-authentication/fingerprinting.md
deleted file mode 100644
index 8ad6701472..0000000000
--- a/articles/cross-origin-authentication/fingerprinting.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: Fingerprinting of Username + Password Login Requests
-description: An explanation of the technique used to mitigate CSRF attacks for cross-origin authentication requests.
----
-# Fingerprinting of Username + Password Login Requests
-
-Auth0 has announced a [vulnerability](https://auth0.com/blog/managing-and-mitigating-security-vulnerabilities-at-auth0/) in all versions of Lock (<11) and auth0.js (<9). We strongly recommend that all users of legacy versions migrate to the newest, most secure versions immediately. Support for conducting logins with a username and password with these versions is now end of life and deprecated versions will stop working on **July 16th, 2018**.
-
-* [Migration Guide for Lock v11](/libraries/lock/v11/migration-guide)
-* [Migration Guide for Auth0.js](/libraries/auth0js/v9/migration-guide)
-
-To help customers reduce their risk before the July 16th deadline a mitigation has been applied to Auth0 server requests from the deprecated versions of Lock and Auth0.js. This is not a full fix, but it does increase the complexity required for an attacker to exploit the vulnerability.
-
-Auth0 performs “fingerprinting” on each request to the vulnerable endpoints. This enables Auth0 to compare the original request with subsequent ones. Requests which do not pass this fingerprinting validation are rejected with the following error:
-
-```json
-"type": "f",
-"description": "Unable to verify transaction consistency"
-```
-
-Note that getting this error does not mean that an attack occurred, but merely that the request did not pass the fingerprinting validation. If this error occurs, you may wish to prompt users to retry authentication. If fingerprinting validation issues persist, the only definitive solution is to migrate to the latest version of Lock / Auth0.js.
-
-This feature allows applications which have been unable to update to have more time to do so with less risk, but the requirement to migrate away from these deprecated library versions still stands, and the Removal of Service date for those deprecated library versions is **July 16, 2018**.
diff --git a/articles/cross-origin-authentication/index.md b/articles/cross-origin-authentication/index.md
index 11f6aa7756..8f20a49401 100644
--- a/articles/cross-origin-authentication/index.md
+++ b/articles/cross-origin-authentication/index.md
@@ -1,51 +1,55 @@
---
-toc: true
title: Cross-Origin Authentication
-description: An explanation of cross-origin authentication in Auth0 and its compatibility with browsers
+description: An explanation of cross-origin authentication in Auth0 and its compatibility with browsers.
+topics:
+ - cors
+contentType:
+ - index
+ - concept
+useCase:
+ - strategize
---
# Cross-Origin Authentication
-For most situations, Auth0 recommends that authentication transactions be handled via [universal login](/hosted-pages/login). Doing so offers [the easiest and most secure way to authenticate users](guides/login/universal-vs-embedded). However, it is understood that some situations may require that authentication forms be directly embedded in an application. Cross-origin authentication provides a way to do this securely.
+Auth0 strongly recommends that authentication transactions be handled via [Universal Login](/universal-login). Doing so offers [the easiest and most secure way to authenticate users](guides/login/universal-vs-embedded). However, some situations may require that authentication forms be directly embedded in an application. Although not recommended, cross-origin authentication provides a way to do this.
-## What is Cross-Origin Authentication?
+## What is cross-origin authentication?
When authentication requests are made from your application (via the Lock widget or a custom login form) to Auth0, the user's credentials are sent to a domain which differs from the one that serves your application. Collecting user credentials in an application served from one origin and then sending them to another origin can present certain security vulnerabilities, including the possibility of a phishing attack.
-Auth0 provides a [cross-origin authentication flow](https://raw.githubusercontent.com/jaredhanson/draft-openid-connect-cross-origin-authentication/master/Draft-1.0.txt) which makes use of [third-party cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Third-party_cookies). The use of third-party cookies allows Lock and Auth0's backend to perform the necessary checks to allow for secure authentication transactions across different origins. This helps to prevent phishing when creating a single sign-on experience with the Lock widget or a custom login form in your application and it also helps to create a secure login experience even if single sign-on is not the goal.
+Auth0 provides a cross-origin authentication flow which makes use of [third-party cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Third-party_cookies). The use of third-party cookies allows Lock and Auth0's backend to perform the necessary checks to allow for secure authentication transactions across different origins. This helps to prevent phishing when creating a Single Sign-on experience with the Lock widget or a custom login form in your application and it also helps to create a secure login experience even if SSO is not the goal.
::: note
-Cross-origin authentication is only necessary when authenticating against a directory using a username and password. Social IdPs and enterprise federation use a different mechanism, redirecting via standard protocols like OpenID Connect and SAML. Additionally, cross-origin authentication is only applicable to embedded login on the web (using Lock or auth0.js). Native applications using embedded login make use of the standard OAuth 2.0 token endpoint.
+Cross-origin authentication is not recommended and is only necessary when authenticating against a directory using a username and password. Social IdPs and enterprise federation use a different mechanism, redirecting via standard protocols like OpenID Connect and SAML. Additionally, cross-origin authentication is only applicable to embedded login on the web (using Lock or auth0.js). Native applications using embedded login make use of the standard OAuth 2.0 token endpoint.
:::
-### Security in deprecated library versions
+## Limitations
-Cross-origin authentication performed using deprecated versions of the [Lock](/libraries/lock) (< v11) and [Auth0.js](/libraries/auth0js) (< v9) libraries is [unsafe](https://auth0.com/blog/managing-and-mitigating-security-vulnerabilities-at-auth0/), and the deprecated versions will be removed from service on July 16, 2018. For any applications which have yet to update and are still using embedded login from those deprecated libraries, a mitigation to the danger has been applied. All requests to the deprecated endpoints from those applications will be [fingerprinted](/cross-origin-authentication/fingerprinting), to allow the Auth0 server to compare the request with previous ones and further mitigate risks. This measure does not prevent attacks, nor does it remove the need to migrate applications.
-
-## Limitations of Cross-Origin Authentication
-
-Because cross-origin authentication is achieved using third-party cookies, disabling third-party cookies will make cross-origin authentication fail.
+Because cross-origin authentication is achieved using third-party cookies, disabling third-party cookies will make cross-origin authentication fail. Some browsers, such as the newest version of Firefox, disable third-party cookies by default, meaning that cross-origin authentication will not work for users on Firefox. The only way to make embedded login work for Firefox users is to use a custom domain, as described below.
There are two approaches you can follow to remediate the issue:
-- Enable [Custom Domains](/custom-domains) and host your web application in a domain that has the same top level domain as the Auth0 custom domain. This way the cookies are no longer third-party and are not blocked by browsers.
-- Provide a [Cross-Origin verification page](#create-a-cross-origin-verification-page) that will make cross-origin authentication work **in some browsers** even with third-party cookies disabled (see the [browser testing matrix](#browser-testing-matrix) below).
+- Enable a [Custom Domain](/custom-domains) on your tenant and host your web application in a domain that has the same top-level domain as your Auth0 custom domain. For example, you host an application at `https://northwind.com` and set your Auth0 custom domain as `https://login.northwind.com`. This way the cookies are no longer third-party (because both your Auth0 tenant and your application are using the same top-level domain), and thus, are not blocked by browsers.
+- Provide a [cross-origin verification page](#create-a-cross-origin-verification-page) that will make cross-origin authentication work in a **limited number of browsers** even with third-party cookies disabled (see the [browser testing information](#browser-testing-support) below).
-These issues are another reason why the more practical solution is to use [universal login](/hosted-pages/login).
+These issues are another reason why the more practical solution is to use [Universal Login](/universal-login).
-## Configure Your Application for Cross-Origin Authentication
+## Configure your application for cross-origin authentication
Configuring your application for cross-origin authentication is a process that requires a few steps:
-1. Ensure that the **Allowed Web Origins** field is set to the domain making the request. You can find this field in the [Application Settings](${manage_url}/#/applications/${account.clientId}/settings). Please note that the URLs specified for Allowed Web Origins **cannot** contain wildcards or relative paths after the domain.
+1. Ensure that the **Allowed Web Origins** field in the [Application Settings](${manage_url}/#/applications/${account.clientId}/settings) is set to the domain making the request. Note that the URLs specified for Allowed Web Origins **cannot** contain wildcards or relative paths after the domain.
1. Ensure that your application is using [Lock](/libraries/lock) 11 or higher, or [Auth0.js](/libraries/auth0js) version 9 or higher.
-1. If you don't enable [Custom Domains](/custom-domains), you will need to author a page which uses auth0.js to act as a fallback for the cross-origin transaction. More information on setting up this page is provided below.
+1. If you don't enable [Custom Domains](/custom-domains), you will need to create a page which uses auth0.js to act as a fallback for the cross-origin transaction. More information on setting up this page is provided below.
-## Create a Cross-Origin Verification Page
+## Create a cross-origin verification page
-There are some cases when third party cookies will not be available. Certain browser versions do not support third party cookies and, if they do, there will be times that they will be disabled in a user's settings. You can use **auth0.js** in your application on a dedicated page to properly handle cases when third-party cookies are disabled. **This page must be served over SSL**.
+There are some cases when third-party cookies will not be available. Certain browser versions do not support third party cookies and, if they do, there will be times that they will be disabled in a user's settings. You can use auth0.js in your application on a dedicated page to properly handle cases when third-party cookies are disabled. **This page must be served over SSL**.
+
+Using `crossOriginVerification` as a fallback will only work if the browser is on the support matrix as **Yes** under **Third-Party Cookies Disabled**. For some browsers, such as **Chrome**, **Opera**, and **Safari**, when third-party cookies are disabled, cross-origin authentication will not work at all unless you enable [Custom Domains](/custom-domains).
::: note
-Note that using `crossOriginVerification` as a fallback will only work if the browser is on the support matrix as **Yes** under "Third-Party Cookies Disabled". For some browsers, such as **Chrome** and **Opera** (Desktop & Android versions of both), when third party cookies are disabled, cross-origin authentication will not work at all unless you enable [Custom Domains](/custom-domains).
+**Safari's** configuration is labeled as "Prevent cross-site tracking" and uses [Intelligent Tracking Prevention](https://webkit.org/blog/7675/intelligent-tracking-prevention/). Unfortunately, this also prevents third-party cookies from being useful in authentication scenarios. Here's an example of how it affects [token renewal](/api-auth/token-renewal-in-safari).
:::
Provide a page in your application which instantiates `WebAuth` from [auth0.js](/libraries/auth0js). Call `crossOriginVerification` immediately. The name of the page is at your discretion.
@@ -56,119 +60,32 @@ Provide a page in your application which instantiates `WebAuth` from [auth0.js](
```
-When third party cookies are not available, **auth0.js** will render an `iframe` which will be used to call a different cross-origin verification flow.
+When third party cookies are not available, auth0.js renders an `iframe` to call a different cross-origin verification flow.
Add the URL of this callback page to the **Cross-Origin Verification Fallback** field in your Application's settings in the [Dashboard](${manage_url}), under the **Advanced > OAuth** panel.
+For production environments, verify that the Location URL for the page does not point to localhost.
+
::: note
-See the [cross-origin auth sample](https://github.com/auth0/lock/blob/master/support/callback-cross-auth.html) for more detail.
+See the [cross-origin auth sample](https://github.com/auth0/lock/blob/master/support/callback-cross-auth.html) for more information.
:::
<%= include('../_includes/_co_authenticate_errors', { library : 'Auth0.js v9 (and Lock v11)'}) %>
-## Browser Testing Matrix
-
-This table lists which browsers can use cross-origin authentication when third-party cookies are disabled.
-
-
-
-
-
-
OS
-
Browser
-
Cross-Origin Authentication Supported with Third-Party Cookies Disabled
-
-
-
-
-
Windows
-
IE
-
Yes
-
-
-
Windows
-
Edge
-
Yes
-
-
-
Windows
-
Firefox
-
Yes
-
-
-
Windows
-
Chrome
-
No
-
-
-
Windows
-
Opera
-
No
-
-
-
macOS Sierra
-
Safari
-
Yes
-
-
-
macOS
-
Firefox
-
Yes
-
-
-
macOS
-
Chrome
-
No
-
-
-
macOS
-
Opera
-
No
-
-
-
iOS (iPhone)
-
Safari
-
Yes
-
-
-
iOS (iPhone)
-
Chrome
-
Yes
-
-
-
iOS (iPhone)
-
Firefox
-
Yes
-
-
-
iOS (iPad)
-
Safari
-
Yes
-
-
-
iOS (iPad)
-
Chrome
-
Yes
-
-
-
Android Galaxy S7
-
Chrome
-
No
-
-
-
Android Galaxy S7
-
Firefox
-
Yes
-
-
-
-
+## Browser testing support
+
+The following browsers can use cross-origin authentication when third-party cookies are disabled:
+
+* Microsoft Internet Explorer
+* Microsoft Edge
+
+<%= include('../_includes/_samesite_none') %>
diff --git a/articles/custom-domains/_additional-steps.md b/articles/custom-domains/_additional-steps.md
new file mode 100644
index 0000000000..b5c6c2894d
--- /dev/null
+++ b/articles/custom-domains/_additional-steps.md
@@ -0,0 +1,3 @@
+## Additional steps for specific Auth0 features
+
+There are additional configuration steps you must complete depending on which Auth0 features you are using. See the [Configure Custom Domains for Specific Features](/custom-domains/additional-configuration) document for more information.
\ No newline at end of file
diff --git a/articles/custom-domains/_cloudflare-cname-flattening.md b/articles/custom-domains/_cloudflare-cname-flattening.md
new file mode 100644
index 0000000000..3d1136b98d
--- /dev/null
+++ b/articles/custom-domains/_cloudflare-cname-flattening.md
@@ -0,0 +1,3 @@
+::: panel Turn off Cloudflare CNAME Flattening
+Cloudflare uses a feature called CNAME Flattening, which affects Auth0 verification and certificate renewal in the way that it handles DNS records. With CNAME flattening enabled, Auth0 will be unable to renew your certificates. For details, see [Cloudflare documentation](https://support.cloudflare.com/hc/en-us/articles/200169056-Understand-and-configure-CNAME-Flattening).
+:::
diff --git a/articles/custom-domains/_provide-domain-name.md b/articles/custom-domains/_provide-domain-name.md
new file mode 100644
index 0000000000..8023559bba
--- /dev/null
+++ b/articles/custom-domains/_provide-domain-name.md
@@ -0,0 +1,19 @@
+## Provide your domain name to Auth0
+
+1. Go to [Dashboard > Tenant Settings](${manage_url}/#/tenant).
+2. Select the **Custom Domains** tab.
+
+ <% if (platform === "auth0") { %>
+ 
+3. Enter your custom domain in the provided box, and select **Auth0-managed certificates**.
+ <% } %>
+
+ <% if (platform === "self") { %>
+ 
+3. Enter your custom domain in the provided box.
+ <% } %>
+4. Click **Add Domain**.
+
+ ::: note
+ You can only add one domain per tenant even though the **Add Domain** button still appears after you add a domain.
+ :::
diff --git a/articles/custom-domains/_subscription.md b/articles/custom-domains/_subscription.md
new file mode 100644
index 0000000000..6298b3c024
--- /dev/null
+++ b/articles/custom-domains/_subscription.md
@@ -0,0 +1,3 @@
+::: panel Feature availability
+Auth0 custom domains are available with any paid [subscription plan](${manage_url}/#/tenant/billing/subscription). If you want to manage the SSL/TLS certificates yourself, you will need an **Enterprise** subscription. For more information refer to [Auth0 pricing plans](https://auth0.com/pricing).
+:::
diff --git a/articles/custom-domains/_warning-repeat-steps.md b/articles/custom-domains/_warning-repeat-steps.md
new file mode 100644
index 0000000000..51c2581b83
--- /dev/null
+++ b/articles/custom-domains/_warning-repeat-steps.md
@@ -0,0 +1,3 @@
+::: warning
+If you are unable to complete the verification process within three days, you'll need to repeat these steps.
+:::
\ No newline at end of file
diff --git a/articles/custom-domains/additional-configuration.md b/articles/custom-domains/additional-configuration.md
index c812f205f1..fcbb1039dc 100644
--- a/articles/custom-domains/additional-configuration.md
+++ b/articles/custom-domains/additional-configuration.md
@@ -1,41 +1,45 @@
---
-title: Additional Configuration for Custom Domains
+title: Configure Features to Use Custom Domains
description: Describes the configuration steps you might need to follow in order to set up custom domains, depending on the Auth0 features you are using
toc: true
+topics:
+ - custom-domains
+contentType: how-to
+useCase: customize-domains
---
-# Additional Configuration for Custom Domains
+# Configure Features to Use Custom Domains
-In order to set up custom domains, and depending on the Auth0 features you are using, there might be additional configuration steps you must follow. This article lists the required configuration you must do per feature.
+To configure Auth0 features to use your custom domain, you may need to complete additional steps depending on the features you are using. For example, you may need to make changes before you can use your custom domain in your login page or to call your APIs.
-If you have been using Auth0 for some time and decide to enable a custom domain, you will have to migrate your existing apps and update the settings as described below. Note that existing sessions created at `${account.namespace}` will no longer be valid once you start using your custom domain, so users will have to login again.
+If you have been using Auth0 for some time and decide to enable a custom domain, you will have to migrate your existing apps and update the settings as described below. Note that existing sessions created at `${account.namespace}` will no longer be valid once you start using your custom domain, so users will have to log in again.
-## Prerequisites
+## Prerequisite
-You have already configured and verified your custom domain. If not, see [How to configure custom domains](/custom-domains#how-to-configure-custom-domains).
+You should have already configured and verified your custom domain. To learn how, see [Verify ownership](/custom-domains/auth0-managed-certificates#verify-ownership).
-## Which section is relevant to me?
+## Features
| **Feature** | **Section to read** |
|-|-|
-| You use [universal login](/hosted-pages/login) and you have customized the login page | [Universal login](#universal-login) |
-| You use Lock embedded in your application | [Embedded Lock](#embedded-lock) |
-| You use Auth0.js or other Auth0 SDKs | [Auth0.js and other SDKs](#auth0-js-and-other-sdks) |
-| You want to use your custom domain with Auth0 emails | [Use custom domains in emails](#use-custom-domains-in-emails) |
-| You want to use social identity providers with your custom domain | [Configure social identity providers](#configure-social-identity-providers) |
-| You want to use Google Apps connections with your custom domain | [Configure Google Apps connections](#configure-google-apps-connections) |
-| You issue Access Tokens for your APIs or you access the Auth0 APIs from your application | [APIs](#apis) |
-| You want to use SAML identity providers with your custom domain| [Configure SAML identity providers](#configure-saml-identity-providers) |
-| You want to use SAML applications with your custom domain | [Configure your SAML applications](#configure-your-saml-applications) |
-| You want to use WS-Fed Clients with your custom domain | [Configure your WS-Fed Clients](#configure-your-ws-fed-clients) |
-| You want to use Azure AD connections with your custom domain | [Configure Azure AD connections](#configure-azure-ad-connections) |
-| You want to use ADFS connections with your custom domain | [Configure ADFS connections](#configure-adfs-connections) |
-| You want to use AD/LAP connections with Kerberos support with your custom domain | [Configure AD/LAP connections](#configure-ad-lap-connections) |
-
-## Universal login
-
-If you use [universal login](/hosted-pages/login) and you have customized the login page, you must update the code to use your custom domain.
-
-If you are using [Lock](/libraries/lock), the additional values required in the initialization can be seen in the following sample script:
+| Universal Login with a customized login page | [Universal Login](#universal-login) |
+| Lock embedded in your application | [Embedded Lock](#embedded-lock) |
+| Auth0 SPA SDK, Auth0.js, or other Auth0 SDKs | [Auth0 SPA SDK, Auth0.js, and other SDKs](#auth0-spa-sdk-auth0-js-and-other-sdks) |
+| Custom domain with Auth0 emails | [Use custom domains in emails](#use-custom-domains-in-emails) |
+| Social identity providers | [Configure social identity providers](#configure-social-identity-providers) |
+| G Suite connections with your custom domain | [Configure G Suite connections](#configure-g-suite-connections) |
+| Issue Access Tokens for your APIs or access Auth0 APIs from your application | [APIs](#apis) |
+| SAML Identity Providers | [Configure SAML identity providers](#configure-saml-identity-providers) |
+| SAML applications | [Configure SAML applications](#configure-saml-applications) |
+| WS-Fed applications | [Configure WS-Fed applications](#configure-ws-fed-applications) |
+| Azure AD connections | [Configure Azure AD connections](#configure-azure-ad-connections) |
+| ADFS connections | [Configure ADFS connections](#configure-adfs-connections) |
+| AD/LAP connections with Kerberos support | [Configure AD/LAP connections](#configure-ad-ldap-connections) |
+
+## Universal Login
+
+If you use [Universal Login](/universal-login) and you have customized the login page, you must update the code to use your custom domain. If you use the **default** login page without customization, you do not need to make any changes.
+
+If you are using [Lock](/libraries/lock), you must set the `configurationBaseUrl` and `overrides` options as seen in the following sample script:
```js
var lock = new Auth0Lock(config.clientID, config.auth0Domain, {
@@ -43,46 +47,50 @@ var lock = new Auth0Lock(config.clientID, config.auth0Domain, {
configurationBaseUrl: config.clientConfigurationBaseUrl,
overrides: {
__tenant: config.auth0Tenant,
- __token_issuer: config.auth0Domain
+ __token_issuer: config.authorizationServer.issuer
},
//code omitted for brevity
});
```
-If you use [Auth0.js](/libraries/auth0js) on the hosted login page, you need to set the `overrides` option like this:
+If you use [Auth0.js](/libraries/auth0js) on the Universal Login page, you must set the `overrides` option.
```js
-var webAuth = new new auth0.WebAuth({
- clientID: config.clientID,
- domain: config.auth0Domain,
+var webAuth = new auth0.WebAuth({
+ clientID: config.clientID,
+ domain: config.auth0Domain,
//code omitted for brevity
overrides: {
__tenant: config.auth0Tenant,
- __token_issuer: config.auth0Domain
+ __token_issuer: config.authorizationServer.issuer
},
//code omitted for brevity
});
```
-If you use the **default** login page without customization, you do not need to make any changes.
+::: note
+For most, the Auth0.js and Lock libraries retrieve the tenant name (required for `/usernamepassword/login`) and the issuer (required for `id_token` validation) from the domain. However, if you're a Private Cloud customer who uses a proxy or a custom domain name where the domain name is different from the tenant/issuer, you can use `__tenant` and `__token_issuer` to provide your unique values.
+:::
## Embedded Lock
If you use [Lock](/libraries/lock) v11 embedded in your application, you must update the code to use your custom domain when initializing Lock. You will also need to set the `configurationBaseUrl` to the appropriate CDN URL.
+::: note
+The CDN URL varies by region. Tenants created before 11 June 2020 should use `https://cdn.auth0.com` if the region is the United States, or add `eu` or `au` for Europe or Australia. If your tenant was created after 11 June 2020, use `https://cdn.us.auth0.com` if the region is the United States.
+:::
+
```js
var lock = new Auth0Lock('${account.clientId}', 'YOUR_CUSTOM_DOMAIN', {
//code omitted for brevity
- configurationBaseUrl: 'https://cdn.auth0.com'
+ configurationBaseUrl: 'https://cdn.us.auth0.com'
//code omitted for brevity
});
```
-The CDN URL varies by region. For regions outside of the US, use `https://cdn.[eu|au].auth0.com` (`eu` for Europe or `au` for Australia).
-
-## Auth0.js and other SDKs
+## Auth0 SPA SDK, Auth0.js, and other SDKs
-If you use [Auth0.js](/libraries/auth0js) or [other SDKs](/support/matrix#auth0-sdks), you will have to initialize the SDK using your custom domain. For example, if you are using the auth0.js SDK, you need to set the following.
+If you use the [Auth0 SPA SDK](/libraries/auth0-spa-js), [Auth0.js](/libraries/auth0js), or [other SDKs](/support/matrix#auth0-sdks), you will have to initialize the SDK using your custom domain. For example, if you are using the Auth0.js SDK, you must set the following:
```js
webAuth = new auth0.WebAuth({
@@ -91,82 +99,102 @@ webAuth = new auth0.WebAuth({
});
```
+And for the Auth0 SPA SDK:
+
+```js
+const auth0 = await createAuth0Client({
+ domain: 'YOUR_CUSTOM_DOMAIN',
+ client_id: '${account.clientId}'
+});
+```
+
+::: note
Note that the Management API only accepts Auth0 domains. If you use a custom domain and also intend to perform [Management API actions with Auth0.js](/libraries/auth0js/v9#user-management), you must instantiate a new copy of `webAuth` using your Auth0 domain.
+:::
## Use custom domains in emails
-If you want to use your custom domain with your Auth0 emails, you must enable this feature.
+If you want to use your custom domain with your Auth0 emails, you must enable this feature.
-Go to [Dashboard > Tenant Settings > Custom Domains](${manage_url}/#/tenant/custom_domains) and enable the **Use Custom Domain in Emails** toggle. When the toggle is green, this feature is enabled.
+Go to [Dashboard > Tenant Settings > Custom Domains](${manage_url}/#/tenant/custom_domains), and enable the **Use Custom Domain in Emails** toggle. When the toggle is green, this feature is enabled.

## Configure social identity providers
-If you want to use social identity providers with your custom domain, you must update the [Allowed Callback URLs](${manage_url}/#/applications/${account.clientId}/settings) to include your custom domain (such as `https://login.northwind.com/login/callback`).
+If you want to use your custom domain with social identity providers, you must update your applications' [Allowed Callback URLs](${manage_url}/#/applications/${account.clientId}/settings) to include your custom domain (such as `https://login.northwind.com/login/callback`).
::: warning
-You cannot use [Auth0 developer keys](/connections/social/devkeys) with custom domains.
+You cannot use [Auth0 developer keys](/connections/social/devkeys) with custom domains unless you are using the [New Universal Login Experience](/universal-login/new).
:::
-
-## Configure Google Apps connections
-If you want to use Google Apps connections with your custom domain, you must update the Authorized redirect URI in your OAuth Client Settings. In the Google Developer Console, go to **Credentials**, choose your OAuth client in the list, and you will see a settings page with the app Client ID, secret, and other fields. In the **Authorized redirect URIs** field, add a URL in the format `https:///login/callback` that includes your custom domain (such as `https://login.northwind.com/login/callback`).
+## Configure G Suite connections
+
+If you want to use your custom domain with G Suite connections, you must update the Authorized redirect URI in your OAuth Client Settings. In the Google Developer Console, go to **Credentials**, choose your OAuth client in the list, and you will see a settings page with the app Client ID, secret, and other fields. In the **Authorized redirect URIs** field, add a URL in the format `https:///login/callback` that includes your custom domain (such as `https://login.northwind.com/login/callback`).
## APIs
-If you use Auth0 with a custom domain to issue Access Tokens for your APIs, then you must validate the JWT issuer(s) against your custom domains. For example, if you use the [express-jwt](https://github.com/auth0/express-jwt) middleware, you must do the following change.
+If you use Auth0 with a custom domain to issue Access Tokens for your APIs, you must validate the JWT issuer(s) against your custom domain. For example, if you use the [express-jwt](https://github.com/auth0/express-jwt) middleware, you must make the following change:
```js
-app.use(jwt({
- issuer: 'https://YOUR-CUSTOM-DOMAIN',
+app.use(jwt({
+ issuer: 'https://',
+ algorithms: ["RS256"],
//code omitted for brevity
}));
```
## Configure SAML identity providers
-If you want to use SAML identity providers (IdPs) with your custom domain, you must get the service provider metadata from Auth0 (such as `https://YOUR-CUSTOM-DOMAIN/samlp/metadata?connection=YOUR-CONNECTION-NAME`). This includes updated **Assertion Consumer Service (ACS) URLs**. Then, you have to manually update this value in your IdP(s). This change to your IdP(s) must happen at the same time as you begin using your custom domain in your applications. This can pose a problem if there are multiple IdPs to configure.
+To use your custom domain with SAML Identity Providers (IdPs), you must update your **Assertion Consumer Service (ACS) URL(s)** with the Identity Provider(s). Depending on what is supported by the IdP, you can do this in one of two ways:
-Alternatively, you can use signed requests to fulfill this requirement:
+1. You can get the service provider metadata from Auth0 at `https:///samlp/metadata?connection=`. This will include the updated ACS URL. Then, you must manually update this value in your IdP(s) settings. This change to your IdP(s) must happen at the same time as you begin using your custom domain in your applications. This can pose a problem if there are multiple IdPs to configure.
-- Once your custom domain is set up, go to [Dashboard > Tenant Settings > Custom Domains](${manage_url}/#/tenant/custom_domains) and download the certificate from the link under the **Sign Request** toggle
-- Give the certificate to the IdP(s) to upload. This enables the IdP to validate the signature on the `AuthnRequest` message that Auth0 sends to the IdP
-- The IdP will import the certificate and if necessary, signature verification should be enabled (exact steps vary by IdP)
-- Turn on the **Sign Request** toggle in the Dashboard under **Connections > Enterprise > SAMLP > CONNECTION**. This will trigger Auth0 to sign the SAML `AuthnRequest` messages it sends to the IdP
+2. If supported by the IdP, you can use signed requests to fulfill this requirement:
-Once this is done, and you start using your custom domain when you initiate an authentication request in your application, the IdP will receive that custom domain in your signed request. Because your application’s signed request is trusted, the IdP should automatically override whatever was configured as your ACS URL and replace it with the value sent in the signed request. However, there are IdPs that do **not** accept the ACS URL in the signed request, so you must check with yours to confirm whether this is supported or not.
+ - Download the signing certificate from `https://.auth0.com/pem`. Note that `https://.com/pem` will return the same certificate
+ - Give the certificate to the IdP(s) to upload. This enables the IdP to validate the signature on the `AuthnRequest` message that Auth0 sends to the IdP
+ - The IdP will import the certificate and, if necessary, signature verification should be enabled (exact steps vary by IdP)
+ - Turn on the **Sign Request** toggle in the Dashboard under **Connections > Enterprise > SAML > CONNECTION**. This will trigger Auth0 to sign the SAML `AuthnRequest` messages it sends to the IdP.
-If this is supported, it will prevent you from having to change one or many IdP settings all at the same time, and allow you to prepare them to accept your signed requests ahead of time, one by one. You can then at a later date have the IdPs change the statically configured ACS URL as well.
+Once this is done, and you start using your custom domain when you initiate an authentication request in your application, the IdP will receive that custom domain in your signed request. Because your application’s signed request is trusted, the IdP should automatically override whatever was configured as your ACS URL and replace it with the value sent in the signed request. However, there are IdPs that do **not** accept the ACS URL in the signed request, so you must check with yours first to confirm whether this is supported or not.
-Note that if your Identity Provider is configured to use the Auth0 custom domains, testing the connection via the **Try** button in the Dashboard will **not** work and the default links for downloading metadata from Auth0 will always show the default domain, not the custom domain.
+If this is supported, it will prevent you from having to change one or many IdP settings all at the same time and allow you to prepare them to accept your signed requests ahead of time. You can then change the statically configured ACS URL in your IdP settings at a later date as well.
+
+Note that if your SAML identity provider is configured to use your custom domain, testing the connection via the **Try** button in the Dashboard will **not** work and the default links for downloading metadata from Auth0 will always show the default domain, not the custom domain.
If you have an IdP-initiated authentication flow, you will need to update the IdP(s) and your application(s) at the same time to use the custom domain.
-## Configure your SAML applications
+## Configure SAML applications
-If you want to use SAML applications with your custom domain, you must update your Service Provider with new Identity Provider metadata from Auth0 (You can obtain the metadata reflecting the custom domain from: `https://YOUR-CUSTOM-DOMAIN/samlp/metadata/YOUR-CLIENT-ID`). Note that the issuer entity ID for the assertion returned by Auth0 will change when using a custom domain (from something like `urn:northwind.auth0.com` to the custom domain such as `urn:login.northwind.com`).
+If you want to use your custom domain with SAML applications (when Auth0 is the IdP), you must update your service provider with new identity provider metadata from Auth0. You can obtain the updated metadata reflecting the custom domain from `https:///samlp/metadata/`. Note that the issuer entity ID for the assertion returned by Auth0 will change when using a custom domain (from something like `urn:northwind.auth0.com` to one with the custom domain, such as `urn:login.northwind.com`).
-If you have an IdP-initiated authentication flow, you will need to update the URL used to invoke the IdP-initiated authentication flow to reflect the custom domain. Instead of `https://.auth0.com/saml/` you should use `https:///saml/`.
+If you have an IdP-initiated authentication flow, you will need to update the URL used to invoke the IdP-initiated authentication flow to reflect the custom domain. Instead of `https://.auth0.com/samlp/`, you should use `https:///samlp/`.
-If you use the Auth0 APIs, such as the Management API, the API identifier will use your default tenant domain name (such as `https://${account.namespace}/userinfo` and `https://${account.namespace}/api/v2/`)
+If you use the Auth0 APIs, such as the Management API, the API identifier will use your default tenant domain name (such as `https://${account.namespace}/userinfo` and `https://${account.namespace}/api/v2/`).
-## Configure your WS-Fed Clients
+## Configure WS-Fed applications
-If you want to use your WS-Fed applications with your custom domain with Auth0 as the IDP, you must update your Service Provider with new Identity Provider metadata from Auth0 (You can obtain the metadata reflecting the custom domain from: `https:///wsfed/FederationMetadata/2007-06/FederationMetadata.xml`).
+If you want to use your custom domain with WS-Fed applications with Auth0 as the IdP, you must update your Service Provider with new identity provider metadata from Auth0. You can obtain the metadata reflecting the custom domain from `https:///wsfed/FederationMetadata/2007-06/FederationMetadata.xml`.
## Configure Azure AD connections
-If you want to use Azure AD connections with your custom domain, you must update the Allowed Reply URL in your Azure AD settings. In your Azure Active Directory, go to **Apps registrations** and select your app. Then click **Settings -> Reply URLs** and add a URL in the format `https:///login/callback` that includes your custom domain (such as `https://login.northwind.com/login/callback`).
+If you want to use your custom domain with Azure AD connections, you must update the Allowed Reply URL in your Azure AD settings. In your Azure Active Directory, go to **Apps registrations** and select your app. Then click **Settings -> Reply URLs** and add a URL with your custom domain in the format `https:///login/callback` (such as `https://login.northwind.com/login/callback`).
## Configure ADFS connections
-The process is the same as [setting up the ADFS connection normally](/connections/enterprise/adfs) except that your callback URL needs to be changed from this format `https://.auth0.com/login/callback` to this one use `https:///login/callback`.
+If you want to use your custom domain with ADFS connections, you must update the endpoint in your ADFS settings. This will need to be updated to use your custom domain in the callback URL in the format `https:///login/callback` (such as `https://login.northwind.com/login/callback`).
## Configure AD/LDAP connections
-If Kerberos support is not needed, AD/LDAP connections should not require further configuration.
+If you do not need Kerberos support, AD/LDAP connections do not require further configuration.
+
+In order to use AD/LDAP connections with Kerberos support, you will need to update the ticket endpoint to work with the custom domain. As mentioned in the [Auth0 AD/LDAP connector documentation](/connector/modify#point-an-ad-ldap-connector-to-a-new-connection), the `config.json` file needs to be modified, with the `PROVISIONING_TICKET` value changed to use your custom domain in the format `https:///p/ad/jUG0dN0R`.
+
+Once this change is saved, you need to restart the AD/LDAP Connector service for the change to take effect.
-In order to use AD/LDAP connections with Kerberos support, you will need to update the ticket endpoint to work with the custom domain. As mentioned in the [Auth0 AD/LDAP connector documentation](/connector/modify#point-an-ad-ldap-connector-to-a-new-connection), the `config.json` file needs to be modified, with the `PROVISIONING_TICKET` value changed from this format `https://.auth0.com/p/ad/jUG0dN0R/info` to `https:///p/ad/jUG0dN0R/info`.
+## Keep reading
-Once this change is saved, be sure to restart the AD/LDAP Connector service.
+* [Configure Custom Domains with Auth0-Managed Certificates](/custom-domains/auth0-managed-certificates)
+* [Configure Custom Domains with Self-Managed Certificates](/custom-domains/self-managed-certificates)
+* [Troubleshooting Custom Domains](/custom-domains/troubleshoot)
diff --git a/articles/custom-domains/auth0-managed-certificates.md b/articles/custom-domains/auth0-managed-certificates.md
new file mode 100644
index 0000000000..e71cbcdc37
--- /dev/null
+++ b/articles/custom-domains/auth0-managed-certificates.md
@@ -0,0 +1,64 @@
+---
+title: Configure Custom Domains with Auth0-Managed Certificates
+description: Learn how to configure custom domains where Auth0 manages the SSL/TLS certificates.
+topics:
+ - custom-domains
+ - certificates
+ - SSL/TLS-certificates
+contentType: how-to
+useCase:
+ - configure-customize-domains
+ - configure-auth0-managed-certificates
+---
+
+# Configure Custom Domains with Auth0-Managed Certificates
+
+<%= include('./_subscription') %>
+
+If you want Auth0 to manage the certificates for your custom domain, you only need to add a CNAME record on the domain. Auth0 validates the record and then generates the certificate on Auth0 servers. These certificates are renewed automatically every three months. You can configure this easily, and you won't have to maintain the certificates yourself.
+
+To set up your custom domain using Auth0-managed certificates, you must provide your domain name to Auth0 and verify that you own that domain. Once verified, you will need to configure your Auth0 features to start using your custom domain.
+
+<%= include('./_provide-domain-name', { platform: 'auth0' }) %>
+
+## Verify ownership
+
+Before you can use the domain with Auth0, you'll need to verify that you own it.
+
+1. Go to [Dashboard > Tenant Settings](${manage_url}/#/tenant), and add the CNAME verification record listed in the Dashboard to your domain's DNS record.
+
+ 
+
+2. Click **Verify** to proceed.
+
+ It may take a few minutes before Auth0 is able to verify your CNAME record, depending on your DNS settings. If Auth0 was able to verify your domain name, you'll see a confirmation window. This means the verification process is complete, and within 1 to 2 minutes, your custom domain should be ready to use.
+
+::: panel Add the CNAME verification record to your domain's DNS record
+Once added, the CNAME record must be present at all times to avoid issues during certificate renewal. If your DNS provider enables a proxy on the CNAME record by default, it will leave the custom domain in a pending state indefinitely. You may need to check your DNS provider settings and disable the proxy. The following steps may vary for your domain host provider.
+
+1. Log in to your domain management service.
+
+2. Create a new record.
+
+ | Parameter | Value |
+ | -- | -- |
+ | **Record type** | **CNAME** |
+ | **Name** | Enter your custom domain name (such as **login.northwind.com**). |
+ | **Time to Live (TTL)** | Use default value |
+ | **Value** | Paste in the **CNAME** value provided by the Auth0 Dashboard for your domain's DNS record. |
+
+3. When done, save your record.
+:::
+
+If Auth0 was able to verify your domain name, you'll see a confirmation window. This means the verification process is complete, and within 1 to 2 minutes, your custom domain should be ready to use.
+
+ 
+
+<%= include('./_warning-repeat-steps') %>
+
+<%= include('./_additional-steps') %>
+
+## Keep reading
+
+* [Troubleshooting Custom Domains](/custom-domains/troubleshoot)
+* [Configure Custom Domains with Self-Managed Certificates](/custom-domains/self-managed-certificates)
diff --git a/articles/custom-domains/index.md b/articles/custom-domains/index.md
index ccffd8daf7..2c1e617b13 100644
--- a/articles/custom-domains/index.md
+++ b/articles/custom-domains/index.md
@@ -1,162 +1,105 @@
---
title: Custom Domains
-description: How to map custom domains
-toc: true
+description: Understand how Auth0 custom domains work so that you can map your tenant domain to a domain of your choosing instead of redirecting users to Auth0's domain.
+topics:
+ - custom-domains
+ - whitelisting
+ - custom-domain features
+ - certificates
+contentType:
+ - index
+ - concept
+useCase: customize-domains
---
# Custom Domains
-Auth0 allows you to map the domain for your tenant to a custom domain of your choosing. This allows you to maintain a consistent experience for your users by keeping them on your domain instead of redirecting or using Auth0's domain.
+<%= include('./_subscription') %>
-For example, if your Auth0 domain is **northwind.auth0.com**, you can have your users to see, use, and remain on **login.northwind.com**.
+Auth0 allows you to map the domain for your tenant to **one custom domain** of your choosing. This allows you to maintain a consistent experience for your users by keeping them on your domain instead of redirecting or using Auth0's domain. You must register and own the domain name to which you are mapping your Auth0 domain. For example, if your Auth0 domain is **northwind.auth0.com**, you can have your users to see, use, and remain on **login.northwind.com**.
-Using custom domains with universal login is the most seamless and secure experience for developers and end users. For more information, please see our docs on [universal login](/hosted-pages/login).
+We recommend that you use custom domains with Universal Login for the most seamless and secure experience for your users. See [Universal Login](/universal-login) to determine if your use case requires custom domains.
-## Prerequisites
+## Token issuance
-You'll need to register and own the domain name to which you're mapping your Auth0 domain.
+Auth0 issues tokens with the **iss** claim of whichever domain you used with the request. For example:
-## Features supporting use of custom domains
-
-Currently, the following Auth0 features and flows support the use of custom domains:
-
-* OAuth 2.0/OIDC-Compliant flows (those using the [`/authorize`](/api/authentication#authorize-application) and [`/oauth/token`](/api/authentication#get-token) endpoints)
-* Guardian (MFA Widget Version 1.3.3/Guardian.js Version 1.3.0 or later)
-* Emails (the links included in the emails will use your custom domain)
-* Database and social connections
-* Lock 11 with cross-origin authentication
-* Passwordless connections with Universal Login (The email link will be sent using the custom domain if the option is enabled in **Tenant Settings > Custom Domains**)
-* Google Apps connections
-* SAML connections and applications
-* WS-Fed clients (Auth0 as IDP using WS-Fed Add-on)
-* Azure AD connections
-* ADFS connections
-* AD/LDAP connections
-
-:::warning
-Features not in the list are **not supported** by Auth0 with custom domains.
-:::
-
-::: panel Token issuance
-Auth0 issues tokens with the **iss** claim of whichever domain you used with the request. For example, if you used **https://northwind.auth0.com/authorize...** to obtain an Access Token, the **iss** claim of the token you receive will be **https://northwind.auth0.com/**. If you used your custom domain **https://login.northwind.com/authorize...**, the **iss** claim value will be **https://login.northwind.com/**.
+| If you use | **iss** claim value with custom domain |
+| -- | -- |
+| `https://northwind.auth0.com/authorize...` | `https://northwind.auth0.com/` |
+| `https://login.northwind.com/authorize...` | `https://login.northwind.com/` |
+::: note
If you get an Access Token for the [Management API](/api/management/v2) using an authorization flow with your custom domain, you **must** call the Management API using the custom domain (your token will be considered invalid otherwise).
:::
-## Certificate management
-
-Auth0 offers two certificate management options.
-
-* **Auth0-Managed Certificates**: Auth0-managed certificates are those where Auth0 will manage the creation and renewal of the certificates for your custom domain. This is the simplest custom domains deployment option, and the scope of this document
+## Metadata endpoints
-* **Self-Managed Certificates**: [Self-managed certificates](/custom-domains/self-managed-certificates) are available for enterprise customers only. Choosing this option means that you are responsible for managing your SSL/TLS certificates and configuring a reverse proxy to handle SSL termination and forwarding requests to Auth0.
+Auth0 implements certain metadata endpoints to ease interoperability and configuration of third-party IdPs and
+applications. When these metadata contain URIs pointing back to Auth0, the URL can either use the Auth0 subdomain or
+your custom domain depending on the hostname used to request the metadata.
-## How to configure custom domains
+| If you use | Reference inside metadata |
+| -- | -- |
+| `https://northwind.auth0.com/.well-known/...` | `https://northwind.auth0.com/...` |
+| `https://northwind.auth0.com/samlp/metadata/...` | `https://northwind.auth0.com/...` |
+| `https://login.northwind.com/samlp/metadata/...` | `https://login.northwind.com/...` |
-Setting up your custom domain using Auth0-managed certificates requires you to do the following steps:
+This applies to the following features:
+- [OpenID Connect Discovery](/protocols/oidc/openid-connect-discovery)
+- [Auth0 as a SAML SP](/protocols/saml/saml-sp-generic)
+- [Auth0 as a SAML Identity Provider](/protocols/saml/saml-idp-generic)
-1. Provide your domain name to Auth0
-1. Verify ownership
-1. Complete feature-specific setup
+## Whitelisting
-### Step 1: Provide your domain name to Auth0
+Be aware that Auth0 does not provide a static list of IP addresses because they are subject to change. We recommend that you whitelist your custom domain instead.
-Log in to the Dashboard and go to [Tenant Settings](${manage_url}/#/tenant). Click over to the **Custom Domains** tab.
+## Exceptions
-
+You can use either your `${account.namespace}` domain to access Auth0 or your custom domain. There are, however, a few exceptions:
-Enter your custom domain in the provided box and select **Auth0-managed certificates**. Click **Add Domain**.
+- If you use embedded Lock or an SDK, the configuration is pre-defined to use either your custom domain or the `${account.namespace}` domain, so you have to use one or the other.
+- If you start a session in `${account.namespace}`, and go to `custom-domain.com`, the user will have to login again.
-### Step 2: Verify ownership
+## Auth0 features that use custom domains
-Before you can use this domain, you'll need to verify that you own your domain. To do this, you need to add the CNAME verification record listed in the Dashboard to your domain's DNS record.
-
-
-
-When you've done so, click **Verify** to proceed.
+The following Auth0 features can use custom domains. See [Configure Custom Domains for Specific Features](/custom-domains/additional-configuration) for details.
::: note
-It may take a few minutes before Auth0 is able to verify your CNAME record, depending on your DNS settings.
-:::
-
-::: panel TL;DR;
-Here's how to add the CNAME verification record to your domain's DNS record. The steps specified may vary by domain host provider, but generally speaking, you will need to:
-
-1. Log in to your domain management service (such as GoDaddy or Google Domains)
-
-1. Create a new record:
-
- * For the record type, indicate **CNAME**
- * For the **Name** field, enter your custom domain name (such as `login.northwind.com`)
- * Leave the **Time to Live (TTL)** field set to the default value
- * In the **Value** field, paste in the CNAME value provided by the Auth0 Dashboard
-
-When done, save your record.
-:::
-
-If Auth0 was able to verify your domain name, you'll see a confirmation window.
-
-This means the verification process is complete and within 1 to 2 minutes, your custom domain should be ready to use.
-
-
-
-::: warning
-If you are unable to complete the verification process within three days, you'll need to start over.
+Features not in the list are **not supported** by Auth0 with custom domains.
:::
-### Step 3: Additional configuration steps
-
-There may be additional steps you must complete depending on which Auth0 features you are using. See the [Additional Configuration for Custom Domains](/custom-domains/additional-configuration) document for more information.
-
-## FAQ
-
-1. **If I use a custom domain, will I still be able to use my ${account.namespace} domain to access Auth0?**
-
-Yes, you will be able to use either the default `${account.namespace}` or your custom domain. There are however a few exceptions:
-
-- If you are using embedded lock or an SDK, the configuration is pre-defined as using either your custom domain or the `${account.namespace}` domain, so you have to use one or the other
-- If you start a session in `${account.namespace}`, and go to `custom-domain.com`, the user will have to login again
-
-2. **What about support for other features?**
-
-We are planning to support several additional features in the future, including WS-Fed applications and enterprise and Passwordless connections.
-
-3. **How many custom domains can I use per tenant?**
-
-Currently, each tenant on the Auth0 public cloud supports **one** custom domain.
-
-## Troubleshooting
-
-If you are seeing errors, refer to the following troubleshooting steps.
-
-### Custom domain is still pending verification
-
-If you continue to see this error in the Dashboard, make sure that the CNAME record is properly configured in your domain management service.
-
-You can confirm the configuration of your CNAME record using:
-
-* A tool like [Mxtoolbox](https://mxtoolbox.com/CNAMELookup.aspx) or [Google](https://dns.google.com)
-* The `dig` command in your terminal
-
-Please remember that it can take up to 48 hours for the DNS to be propagated.
-
-### CNAME flattening
-
-Cloudflare has a service called CNAME Flattening. During the verification process, turn off the CNAME flattening process until the domain verification steps are complete to prevent IP address confusion.
-
-### Domains with existing CAA records
-
-If your domain, or the parent domain, already has a **Certification Authority Authorization** (CAA) record, then you have to add another one for `letsencrypt.org`.
-
-The reason for that is that Auth0 uses `letsencrypt.org` to sign certificates so if it's not authorized to issue certificates for your domain, the custom domain functionality will not work for you.
-
-To add a new CAA record and whitelist `letsencrypt.org` use the following:
-
-```text
-"0 issue \"letsencrypt.org\""
-```
-
-### "Service not found"
-
-If your application issues an `/authorize` request with `audience=https://login.northwind.com/userinfo`, the server will return a `Service not found: https://login.northwind.com/userinfo` error. This is because even if you set a custom domain the API identifier for the `/userinfo` endpoint remains `https://{YOUR_ORIGINAL_AUTH0_DOMAIN}/userinfo`.
-
-To fix this your app should instead use `audience=https://{YOUR_ORIGINAL_AUTH0_DOMAIN}/userinfo`. You can also remove this `audience=[...]/userinfo` parameter altogether if your application is flagged as **OIDC-Conformant** in the **OAuth2** tab of the application's **Advanced Settings**.
+| Features/Flows | Details |
+| -- | -- |
+| Universal Login | For a seamless and secure user experience |
+| MFA | All factors |
+| Guardian | MFA Widget version 1.3.3/Guardian.js version 1.3.0 or later |
+| Emails | Links included in the emails use your custom domain |
+| Connections | Database, social, G Suite, Azure AD, ADFS, AD/LDAP |
+| Lock | Version 11 with cross-origin authentication |
+| Passwordless | With Universal Login (The email link sent using the custom domain if the option is enabled in **Dashboard > Tenant Settings > Custom Domains**.) |
+| SAML | Connections and applications |
+| WS-Federation | Auth0 as identity provider using WS-Fed add-on |
+| OAuth 2.0/OIDC-Compliant flows | Using the [`/authorize`](/api/authentication#authorize-application) and [`/oauth/token`](/api/authentication#get-token) endpoints |
+
+## Certificate management options
+
+### Auth0-managed certificates
+
+With the [Auth0-managed certificate approach](/custom-domains/auth0-managed-certificates), Auth0 obtains certificates for your domain and then manages the SSL handshake directly with the client.
+
+### Self-managed certificates
+
+With the [self-managed certificate approach](/custom-domains/self-managed-certificates), you are completely responsible for handling the SSL certificates and setting up and managing a reverse proxy for content to be sent to Auth0. Auth0 does not negotiate SSL with the end user’s client, but with the proxy. The proxy in turn negotiates SSL with the end user. To prevent someone from trying to use your Auth0 account from a domain you don’t own, Auth0 needs to validate that the domain belongs to you. Therefore, you need to send Auth0 a header (`cname-api-key`) to validate. You must be an **Enterprise** customer to use this option.
+
+## Keep reading
+
+* [Configure Custom Domains for Specific Features](/custom-domains/additional-configuration)
+* [Universal Login](/universal-login)
+* [Multi-factor Authentication](/mfa)
+* [Emails in Auth0](/email)
+* [Connections](/identityproviders)
+* [Lock v11 for Web](/libraries/lock/v11)
+* [Passwordless Authentication](/api-auth/passwordless)
+* [SAML](/protocols/saml)
+* [WS-Federation](/protocols/ws-fed)
+* [Which OAuth 2.0 Flow Should I Use?](/api-auth/which-oauth-flow-to-use)
diff --git a/articles/custom-domains/self-managed-certificates.md b/articles/custom-domains/self-managed-certificates.md
index e78d716dc3..0d5110075d 100644
--- a/articles/custom-domains/self-managed-certificates.md
+++ b/articles/custom-domains/self-managed-certificates.md
@@ -1,82 +1,127 @@
---
title: Configure Custom Domains with Self-Managed Certificates
-description: How to create custom domains with self-managed certificates
-toc: true
+description: Learn how to configure custom domains where you are responsible for SSL/TLS certificates, the reverse proxy to handle SSL termination, and forwarding requests to Auth0.
+topics:
+ - custom-domains
+ - certificates
+ - reverse-proxy
+ - SSL/TLS-certificates
+contentType: how-to
+useCase:
+ - configure-customize-domains
+ - forward-requests-to-auth0
+ - configure-reverse-proxy
+ - configure-self-managed-certificates
---
-# Custom Domains with Self-Managed Certificates
+# Configure Custom Domains with Self-Managed Certificates
-Custom Domains with the **Self-Managed Certificates** option is available for enterprise customers only. Choosing this option means that you are responsible for managing your SSL/TLS certificates and configuring a reverse proxy to handle SSL termination and forwarding requests to Auth0.
+<%= include('./_subscription') %>
-Choose this option if:
+If you choose to manage the certificates for your custom domains yourself, it requires multiple DNS records on the domain. You have to purchase or provide the certificates from any known Certificate Authority and manage the renewals yourself. You will also need a reverse proxy, where the certificate will be installed. Once the domain is verified, we will accept traffic from the proxy.
-* You want to have more control of your certificates (such as choosing your own CA or certificate expiration)
-* You want to enable additional monitoring over your API calls to Auth0
+Choose this option to:
-## Prerequisites
+* Have more control of your certificates (such as choosing your own CA or certificate expiration).
+* Enable additional monitoring over your API calls to Auth0.
-You'll need to register and own the domain name to which you're mapping your Auth0 domain.
+To set up your custom domain using self-managed certificates, you need to provide your domain name to Auth0, verify that you own that domain, and configure the reverse proxy. Once your custom domain has been set up, you will need to configure your Auth0 features to start using your custom domain.
-## How to Configure Custom Domains with Self-Managed Certificates
+<%= include('./_provide-domain-name', { platform: 'self' }) %>
-Setting up your custom domain with Self-managed certificates requires you to do the following steps:
+## Verify ownership
-1. Provide your domain name to Auth0
-1. Verify ownership
-1. Configure the reverse proxy
-1. Complete feature-specific setup
+Before you can use the domain with Auth0, you'll need to verify that you own it.
-### Step 1: Provide Your Domain Name to Auth0
+1. Go to [Dashboard > Tenant Settings](${manage_url}/#/tenant), and copy the TXT verification record listed in the Dashboard to your domain's DNS record.
-Log in to the Dashboard and go to [Tenant Settings](${manage_url}/#/tenant). Click over to the **Custom Domains** tab.
+ 
-
+::: panel Add the TXT verification record to your domain's DNS record
+The following steps may vary for your domain host provider.
-Enter your custom domain in the provided box and select **Self-managed certificates**. Click **Add Domain**.
+1. Log in to your domain management service.
-### Step 2: Verify Ownership
+2. Create a new record, and save:
-Before you can use this domain, you'll need to verify that you own your domain. To do this, you will need to add the TXT verification record listed in the Dashboard to your domain's DNS record.
+ | Parameter | Value |
+ | -- | -- |
+ | **Record type** | **TXT** |
+ | **Name** | Enter your custom domain name (such as **login.northwind.com**). |
+ | **Time to Live (TTL)** | Use default value |
+ | **Value** | Paste in the **TXT** value provided by the Auth0 Dashboard for your domain's DNS record. |
+:::
-
+ It may take a few minutes before Auth0 can verify your TXT record, depending on your DNS settings.
-When you've done so, click **Verify** to proceed.
+2. Click **Verify** to proceed.
-::: note
-It may take a few minutes before Auth0 is able to verify your TXT record, depending on your DNS settings.
-:::
+ If Auth0 was able to verify your domain name, you'll see a confirmation window.
-::: panel TL;DR
-Here's how to add the TXT verification record to your domain's DNS record. The steps specified may vary by domain host provider, but generally speaking, you will need to:
+ ::: note
+ Save the information provided in this window, specifically the `cname-api-key` value, since this is the **only** time you'll see this value.
+ :::
-1. Log in to your domain management service (such as GoDaddy or Google Domains)
+ 
-1. Create a new record:
+ The verification process is complete, and within 1 to 2 minutes, your custom domain should be ready to use.
- * For the record type, indicate **TXT**
- * For the **Name** field, enter your custom domain name (such as **login.northwind.com**)
- * Leave the **Time to Live (TTL)** field set to the default value
- * In the **Value** field, paste in the TXT value provided by the Auth0 Dashboard
+<%= include('./_warning-repeat-steps') %>
-When done, save your record.
-:::
+## Configure reverse proxy
-If Auth0 was able to verify your domain name, you'll see a confirmation window.
+The reverse proxy server retrieves resources on behalf of your client from one or more servers. These resources are then returned to the client, appearing as if they originated from the proxy server itself.
-Save the information provided in this pop-up, especially the `cname-api-key` value, since this is the **only** time you'll see this value.
+You can use a service such as [Cloudflare](/custom-domains/set-up-cloudflare), [Azure CDN](/custom-domains/set-up-azure-cdn), or [AWS Cloudfront](/custom-domains/set-up-cloudfront) and configure settings for your custom domain. You will add the new CNAME value to your DNS for your custom domain pointing to the reverse proxy server domain name for distribution.
-
+1. After you've created the reverse proxy settings on your service, go to [Dashboard > Tenant Settings](${manage_url}/#/tenant) **Custom Domains** tab.
-This means the verification process is complete and within 1 to 2 minutes, your custom domain should be ready to use.
+2. Add a new CNAME record to your DNS for your custom domain pointing to the service domain name for your distribution. You can find this by looking for the **Distribution ID** on your reverse proxy server configuration.
-::: warning
-If you are unable to complete the verification process within three days, you'll need to start over.
-:::
+ ::: note
+ Once added, the CNAME record must be present at all times to avoid issues during certificate renewal.
+ :::
+
+3. The way you configure the proxy server will vary depending on the service you use. You will likely need to configure the following types of settings:
+
+* [Distribution](#distribution-settings)
+* [Origin custom headers](#origin-custom-header-settings)
+* [Default cache behaviour](#default-cache-behavior-settings)
+
+### Distribution settings
+
+ | Setting | Value |
+ | - | - |
+ | Origin Domain Name | Set this to the **Origin Domain Name** value obtained from the Auth0 Dashboard during the Custom Domains setup process. |
+ | Origin ID | A description for the origin. This value lets you distinguish between multiple origins in the same distribution and therefore must be unique. |
+ | Origin Protocol Policy | Set to `HTTPS Only`. |
+ | Alternate Domain Names (CNAMEs) | Set to your custom domain name (the same one your configured in the Auth0 Dashboard). |
+
+### Origin custom header settings
+
+ | Setting | Value |
+ | -- | -- |
+ | Header Name | Set to `cname-api-key`. |
+ | Value | Set to the CNAME API Key value that you were given immediately after you verified ownership of your domain name with Auth0. |
+
+### Default cache behavior settings
-### Step 3: Configure the Reverse Proxy
+ | Setting | Value |
+ | - | - |
+ | Viewer Protocol Policy | Select **Redirect HTTP to HTTPS**. |
+ | Allowed HTTP Methods | Select **GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE**. |
+ | Cache Based on Selected Request Headers | Select **Whitelist**. |
+ | Whitelist Headers | Enter `User-Agent`, and click **Add Custom >>** to add the custom whitelist header. Do the same for `Origin` and `Referer` headers. |
+ | Forward Cookies | Select **All**. |
+ | Query String Forwarding and Caching | Select **Forward all, cache based on all**. |
-Next you will need to [set up your reverse proxy using AWS CloudFront](/custom-domains/set-up-cloudfront).
+<%= include('./_additional-steps') %>
-### Step 4: Complete Feature-Specific Setup
+<%= include('./_cloudflare-cname-flattening') %>
-There are additional steps you must complete depending on which Auth0 features you are using. Refer to our [custom domains documentation](/custom-domains#step-3-complete-feature-specific-setup) for more details.
+## Keep reading
+* [Troubleshooting Custom Domains](/custom-domains/troubleshoot)
+* [Configure Cloudflare for Use as Reverse Proxy](/custom-domains/set-up-cloudflare)
+* [Configure AWS CloudFront for Use as Reverse Proxy](/custom-domains/set-up-cloudfront)
+* [Configure Azure CDN for Use as Reverse Proxy](/custom-domains/set-up-azure-cdn)
+* [Configure Custom Domains with Auth0-Managed Certificates](/custom-domains/auth0-managed-certificates)
diff --git a/articles/custom-domains/set-up-azure-cdn.md b/articles/custom-domains/set-up-azure-cdn.md
new file mode 100644
index 0000000000..b0a1a6d43e
--- /dev/null
+++ b/articles/custom-domains/set-up-azure-cdn.md
@@ -0,0 +1,60 @@
+---
+name: Configure Azure CDN for Use as Reverse Proxy
+description: Learn how to set up Azure CDN for use as the custom domain proxy for Auth0.
+topics:
+ - custom-domains
+ - azure
+ - cdn
+ - reverse-proxy
+contentType: how-to
+useCase:
+ - customize-domains
+ - self-managed-certificates
+---
+
+# Configure Azure CDN for Use as Reverse Proxy
+
+<%= include('./_subscription') %>
+
+To set up Azure CDN as a reverse proxy, an Azure CDN Premium plan is required.
+
+1. Complete the steps on [Configure Custom Domains with Self-Managed Certificates](/custom-domains/self-managed-certificates) if you haven't already. Make note of the **Origin Domain Name** and **cname-api-key** values since you'll need these later.
+2. Login to the [Azure Portal](https://portal.azure.com/).
+3. [Create a new Azure CDN Profile](https://docs.microsoft.com/en-us/azure/cdn/cdn-create-new-endpoint#create-a-new-cdn-profile).
+4. [Create a new Azure CDN endpoint](https://docs.microsoft.com/en-us/azure/cdn/cdn-create-new-endpoint#create-a-new-cdn-endpoint) using the CDN Profile you just created. For the CDN endpoint settings, use the following values:
+
+ | Setting | Value |
+ |---------|-------|
+ | Name | We recommend naming your CDN endpoint like your custom domain name, replacing dots with dashes. For example: **login-mydomain-com.azureedge.net**. |
+ | Origin type | Select **Custom Origin** |
+ | Origin hostname | Enter `${account.tenant}..edge.tenants.auth0.com`, making sure to replace `` with the custom domain ID from the **Origin Domain Name** you received from Auth0. If your tenants are not in the US region, use one of the following:
|
+ | Origin path | Leave blank. |
+ | Origin host header | Use the name you provided for the Origin hostname. |
+ | Protocol | Disable HTTP so that only HTTPS is enabled. |
+
+5. [Add your custom domain to your Azure CDN endpoint](https://docs.microsoft.com/en-us/azure/cdn/cdn-map-content-to-custom-domain).
+6. [Configure HTTPS for your Azure CDN custom domain](https://docs.microsoft.com/en-us/azure/cdn/cdn-custom-ssl?tabs=option-1-default-enable-https-with-a-cdn-managed-certificate). This process requires you to verify ownership of the domain. Once done, it may take up to 6 hours to deploy the certificate to all of the CDN pop locations.
+7. Set up the configuration for the custom domain communication with Auth0 using the [Azure CDN Rules Engine](https://docs.microsoft.com/en-us/azure/cdn/cdn-verizon-premium-rules-engine). Create [a new Azure CDN Rule](https://docs.microsoft.com/en-us/azure/cdn/cdn-verizon-premium-rules-engine#tutorial) with the following settings:
+
+ | Setting | Value |
+ |---------|-------|
+ | Name/Description | Auth0 Custom Domain |
+ | Type of requests | Select the **Edge CName** option, then select your custom domain name from the list. |
+
+8. Add the following **Features** to your Azure CDN Rule:
+
+ | Setting | Value |
+ |---------|-------|
+ | Bypass Cache | **Enabled** |
+ | Modify Client Request Header | Select **Override**, enter **cname-api-key** for the name, and enter the CNAME API Key provided by Auth0 as the value.
+
+::: note
+We recommend creating another Azure CDN Rule to deny the usage of the **azureedge.net** CNAME.
+:::
+
+9. Once the Azure CDN Rule is approved, the status will change from Pending XML to Active XML. At this point, Azure CDN will be publishing the rules and certificates. When Azure finishes processing all changes, you can use your custom domain.
+
+## Keep reading
+
+* [Troubleshooting Custom Domains](/custom-domains/troubleshoot)
+* [Configure Custom Domains with Self-Managed Certificates](/custom-domains/self-managed-certificates)
diff --git a/articles/custom-domains/set-up-cloudflare.md b/articles/custom-domains/set-up-cloudflare.md
new file mode 100644
index 0000000000..8f03e3c4c0
--- /dev/null
+++ b/articles/custom-domains/set-up-cloudflare.md
@@ -0,0 +1,61 @@
+---
+name: Configure Cloudflare for Use as Reverse Proxy
+description: Learn how to set up Cloudflare for use as the custom domain proxy for Auth0.
+topics:
+ - custom-domains
+ - cloudflare
+ - reverse-proxy
+contentType: how-to
+useCase:
+ - customize-domains
+ - self-managed-certificates
+---
+
+# Configure Cloudflare for Use as Reverse Proxy
+
+<%= include('./_subscription') %>
+
+To set up Cloudflare as a reverse proxy, a Cloudflare Enterprise Plan with the following features is required:
+
+* Host Header Override: [Using Page Rules to Re-Write Host Headers (Cloudflare Support)](https://support.cloudflare.com/hc/en-us/articles/206652947-Using-Page-Rules-to-Re-Write-Host-Headers)
+* True-Client-IP Header: [What is True-Client-IP? (Cloudflare Support)](https://support.cloudflare.com/hc/en-us/articles/206776727-What-is-True-Client-IP-)
+
+<%= include('./_cloudflare-cname-flattening') %>
+
+1. Complete the steps on [Configure Custom Domains with Self-Managed Certificates](/custom-domains/self-managed-certificates) if you haven't already. Make note of the **Origin Domain Name** and **cname-api-key** values since you'll need these later.
+2. [Configure a CNAME setup](https://support.cloudflare.com/hc/en-us/articles/360020615111-Configuring-a-CNAME-setup) with Cloudflare.
+3. Once Cloudflare has verified your domain, log in to the [Cloudflare Dashboard](https://dash.cloudflare.com/login).
+4. [Create a new Cloudflare Page Rule](https://support.cloudflare.com/hc/en-us/articles/200172336-Creating-Page-Rules) with the following settings:
+
+ | Setting | Value |
+ |---------|-------|
+ | Host Header Override | Enter `${account.tenant}..edge.tenants.auth0.com`, replacing `` with the custom domain ID from the **Origin Domain Name** you received from Auth0. If your tenants are not in the US region, use one of the following:
|
+ | True-Client-IP | Select **Enable**. |
+
+5. Next, create and deploy a new [Cloudflare Worker](https://developers.cloudflare.com/workers/) for the configured CNAME using the following script. Replace `` below with the **cname-api-key** you received from Auth0:
+
+ ```js
+ addEventListener('fetch', event => {
+ event.respondWith(handleRequest(event.request))
+ })
+
+ async function handleRequest(request) {
+ request = new Request(request)
+ request.headers.set('cname-api-key', '')
+ return await fetch(request)
+ }
+ ```
+
+## Configure Auth0
+
+Once you've configured Cloudflare, you'll need to Enable **True-Client-IP** header using the management API [/api/v2/custom-domains/{id}](https://auth0.com/docs/api/management/v2#!/Custom_Domains/patch_custom_domains_by_id)
+```curl
+curl -X PATCH -H "Content-Type: application/json" -d '{"custom_client_ip_header":"true-client-ip"}' https://login.auth0.com/api/v2/custom-domains/{id}
+
+```
+
+
+## Keep reading
+
+* [Troubleshooting Custom Domains](/custom-domains/troubleshoot)
+* [Configure Custom Domains with Self-Managed Certificates](/custom-domains/self-managed-certificates)
diff --git a/articles/custom-domains/set-up-cloudfront.md b/articles/custom-domains/set-up-cloudfront.md
index 8f952d3ca5..54fbcfcf7b 100644
--- a/articles/custom-domains/set-up-cloudfront.md
+++ b/articles/custom-domains/set-up-cloudfront.md
@@ -1,60 +1,73 @@
---
-toc: true
name: Configure AWS CloudFront for Use as Reverse Proxy
-description: How to set up AWS CloudFront for use as the custom domain proxy for Auth0
+description: Learn how to configure AWS CloudFront for use as the custom domain proxy for Auth0.
+topics:
+ - custom-domains
+ - aws
+ - cloudfront
+ - reverse-proxy
+contentType: how-to
+useCase:
+ - customize-domains
+ - self-managed-certificates
---
# Configure AWS CloudFront for Use as Reverse Proxy
-In this article, we will show you how to configure AWS CloudFront for use as the reverse proxy with custom domain names for your Auth0 tenant.
-Log in to AWS, and navigate to [CloudFront](https://console.aws.amazon.com/cloudfront).
+<%= include('./_subscription') %>
-
+You can configure AWS CloudFront for use as the reverse proxy with custom domain names for your Auth0 tenant.
-Click **Create Distribution**.
+1. Log in to AWS, and navigate to [CloudFront](https://console.aws.amazon.com/cloudfront).
-You can choose the delivery method for your content. Click **Get Started** under the **Web** section.
+ 
-
+2. Click **Create Distribution**.
-Next, configure your distribution settings.
+3. You can choose the delivery method for your content. Click **Get Started** under the **Web** section.
-Under **Origin Settings**, here are the values you'll need to change:
+ 
-| Parameter | Value |
-| - | - |
-| Origin Domain Name | Set this to the **Origin Domain Name** value obtained from the Auth0 Dashboard during the Custom Domains setup process |
-| Origin ID | A description for the origin. This value lets you distinguish between multiple origins in the same distribution and therefore must be unique. |
-| Origin Protocol Policy | Set to `HTTPS Only` |
-| Alternate Domain Names (CNAMEs) | Set to your custom domain name (the same one your configured in the Auth0 Dashboard) |
+4. Configure your distribution settings. Under **Origin Settings**, here are the values you'll need to change:
-
+ | Setting | Value |
+ | - | - |
+ | Origin Domain Name | Set this to the **Origin Domain Name** value obtained from the Auth0 Dashboard during the Custom Domains setup process |
+ | Origin ID | A description for the origin. This value lets you distinguish between multiple origins in the same distribution and therefore must be unique. |
+ | Origin Protocol Policy | Set to `HTTPS Only` |
+ | Alternate Domain Names (CNAMEs) | Set to your custom domain name (the same one your configured in the Auth0 Dashboard) |
+ | SSL Certificate | Set to the SSL Certificate for your custom domain stored in AWS Certificate Manager (ACM) in the US East(N. Virginia) Region or in IAM. |
-You'll also need to provide information on the **Origin Custom Headers** (the **Header Name** and **Value** fields appear only after you've provided an **Origin Domain Name**):
+ 
-| Parameter | Value |
-| - | - |
-| Header Name | Set to `cname-api-key` |
-| Value | Set to the CNAME API Key value that you were given immediately after you verified ownership of your domain name with Auth0 |
+5. Provide information on the **Origin Custom Headers** (the **Header Name** and **Value** fields appear only after you've provided an **Origin Domain Name**):
-
+ | Setting | Value |
+ | - | - |
+ | Header Name | Set to `cname-api-key` |
+ | Value | Set to the CNAME API Key value that you were given immediately after you verified ownership of your domain name with Auth0 |
-Next, you'll configure the **Default Cache Behavior Settings**. Here are the values you'll need to change:
+ 
-| Parameter | Value |
-| - | - |
-| Viewer Protocol Policy | Select **Redirect HTTP to HTTPS** |
-| Allowed HTTP Methods | Select **GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE** |
-| Cache Based on Selected Request Headers | Select **Whitelist** |
-| Whitelist Headers | Enter `User-Agent` and click **Add Custom >>** to add the custom whitelist header |
-| Forward Cookies | Select **All** |
-| Query String Forwarding and Caching | Select **Forward all, cache based on all** |
+6. Configure the **Default Cache Behavior Settings**. Here are the values you'll need to change:
-Scroll to the bottom of the page and click **Create Distribution**.
+ | Setting | Value |
+ | - | - |
+ | Viewer Protocol Policy | Select **Redirect HTTP to HTTPS** |
+ | Allowed HTTP Methods | Select **GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE** |
+ | Cache Based on Selected Request Headers | Select **Whitelist** |
+ | Whitelist Headers | Enter `User-Agent` and click **Add Custom >>** to add the custom whitelist header. Do the same for `Authorization`, `Origin`, `Referer` and `Accept` headers. |
+ | Forward Cookies | Select **All** |
+ | Query String Forwarding and Caching | Select **Forward all, cache based on all** |
-You'll see your newly-created distribution in your CloudFront Distributions list. Note that the Status will reflect `In progress` until the distribution is Deployed.
+7. Scroll to the bottom of the page and click **Create Distribution**.
-
+ You'll see your newly-created distribution in your CloudFront Distributions list. Note that the Status will reflect `In progress` until the distribution is Deployed.
-Finally, add a new CNAME record to your DNS for your custom domain pointing to the CloudFront Domain Name for your Distribution. This can be found by clicking on your Distribution ID, under the General tab, Domain Name (for example, `e2zwy42nt1feu7.cloudfront.net`).
+ 
-Your CloudFront setup is now ready for use!
+8. Add a new CNAME record to your DNS for your custom domain pointing to the CloudFront Domain Name for your Distribution. This can be found by clicking on your Distribution ID, under the General tab, Domain Name (for example, `e2zwy42nt1feu7.cloudfront.net`).
+
+## Keep reading
+
+* [Troubleshooting Custom Domains](/custom-domains/troubleshoot)
+* [Configure Custom Domains with Self-Managed Certificates](/custom-domains/self-managed-certificates)
diff --git a/articles/custom-domains/troubleshoot.md b/articles/custom-domains/troubleshoot.md
new file mode 100644
index 0000000000..d9139d3eb9
--- /dev/null
+++ b/articles/custom-domains/troubleshoot.md
@@ -0,0 +1,64 @@
+---
+title: Troubleshoot Custom Domains
+description: Learn how to troubleshoot issues with custom domains.
+topics:
+ - custom-domains
+ - certificates
+contentType: reference
+useCase:
+ - configure-customize-domains
+ - configure-auth0-managed-certificates
+---
+
+# Troubleshoot Custom Domains
+
+If you are seeing errors, take a look at this video on common issues with Custom Domains, or refer to the below sections for troubleshooting steps for specific scenarios.
+
+
+
+## Custom domain is still pending verification
+
+It can take up to 48 hours for the DNS to be propagated.
+
+If you continue to see this error in the Dashboard, make sure that the CNAME record is properly configured in your domain management service. You can confirm the configuration of your CNAME record using:
+
+* A tool like [Mxtoolbox](https://mxtoolbox.com/DNSLookup.aspx) or [Google](https://dns.google.com)
+* The `dig` command in your terminal
+
+Ensure that the domain name is not already associated with an A record.
+
+Make sure that no errors were made when typing or copying the CNAME record's domain name or value.
+
+## Cloudflare CNAME Flattening
+
+CNAME Flattening affects the Auth0 verification and certificate renewal processes due to the way it handles DNS records. We recommend turning off CNAME Flattening unless it's strictly necessary, according to the [Cloudflare documentation](https://support.cloudflare.com/hc/en-us/articles/200169056-Understand-and-configure-CNAME-Flattening).
+
+## "You should not be hitting this endpoint"
+If you see this error when configuring a custom domain, you must perform [additional configuration](/custom-domains/additional-configuration), which varies depending on your setup.
+
+## "Service not found"
+
+If your application issues an `/authorize` request with `audience=https://login.northwind.com/userinfo`, the server will return a `Service not found: https://login.northwind.com/userinfo` error. This is because even if you set a custom domain the API identifier for the `/userinfo` endpoint remains `https://{YOUR_ORIGINAL_AUTH0_DOMAIN}/userinfo`.
+
+Similarly, using your custom domain in calls to the [Management API](/api/management/v2) will error for the same reason.
+
+To fix this your app should instead use `audience=https://{YOUR_ORIGINAL_AUTH0_DOMAIN}/userinfo`. You can also remove this `audience=[...]/userinfo` parameter altogether if your application is flagged as **OIDC-Conformant** in the **OAuth2** tab of the application's **Advanced Settings**.
+
+## Errors related to Internet Explorer
+
+If you are using Internet Explorer, you may see any of the following error messages:
+
+* "No verifier returned from client"
+* "Origin header required"
+* "Failed cross origin authentication"
+
+When both the Auth0 domain and the app domain are in the same trusted or local intranet zone, Internet Explorer does *not* treat the request as a cross-domain request and therefore does not send the cross-origins header.
+
+If you see any of these errors and you are using Embedded Login, you can move one of the sites out of the trusted or local intranet zone. To do this:
+
+1. Go to **Internet Options > Security**.
+2. Select the **Local Intranet Zone** tab and go to Sites > Advanced. Add your domain.
+3. Return to the **Security** tab, and make sure the proper zone has been selected.
+4. Click **Custom Level** and look for **Access data sources across domains** under the **Miscellaneous** section. Check the radio button next to **Enable.**.
+
+Alternatively, you can remove reliance on cross-origin authentication by implementing [Universal Login](/universal-login).
diff --git a/articles/dashboard/creating-users-in-the-management-portal.md b/articles/dashboard/creating-users-in-the-management-portal.md
deleted file mode 100644
index 27ddaa809f..0000000000
--- a/articles/dashboard/creating-users-in-the-management-portal.md
+++ /dev/null
@@ -1,44 +0,0 @@
----
-description: How to create users in the Auth0 Dashboard.
-crews: crew-2
----
-
-# Create Users using the Dashboard
-
-You can manually create users via the [Dashboard](${manage_url}).
-
-Log in and open up the Dashboard. Navigate to the _Users_ tab.
-
-
-
-Click on the __Create User__ button near the top right-hand side of the screen.
-
-
-
-4. Provide the following pieces of information for the new user:
- * Email
- * Password
- * Repeat Password (for confirmation)
- * Connection
-
- When finished, click __Save__.
-
-::: note
-The connection you use must be associated with an application, otherwise you will receive an error message that says, The connection is disabled. You can enable connections for Applications from the Dashboard, in Application Settings > Connections, or from the Connection Settings > Applications.
-:::
-
-
-
-At this point, the user is created, and you will be directed to the newly-created user's profile.
-
-
-
-::: panel Pending Users
-The User Details page will show `pending` when a user is first created until they have logged in for the first time.
-:::
-
-## Keep reading
-
-::: next-steps
-* [Learn more about managing your Users](/user-profile)
-:::
diff --git a/articles/dashboard/dashboard-tenant-settings.md b/articles/dashboard/dashboard-tenant-settings.md
deleted file mode 100644
index aff764bd9f..0000000000
--- a/articles/dashboard/dashboard-tenant-settings.md
+++ /dev/null
@@ -1,96 +0,0 @@
----
-description: Explains what features and settings can be changed in the Tenant Settings page of the dashboard.
-toc: true
----
-# Tenant Settings in the Auth0 Dashboard
-
-The [Tenant Settings](${manage_url}/#/tenant) page of the dashboard allows you to configure various settings related to your Auth0 tenant.
-
-## General
-
-The following sections can be found on the initial page you're redirected to when opening up the settings area.
-
-### Settings
-
-
-
-Use this section to customize some of the settings related to your tenant. These settings will be used in [Lock](https://auth0.com/lock), emails and various other pages being displayed to your end users.
-
-* **Friendly Name**: This is the name you want to be displayed to your users, usually the name of your company or organization.
-* **Logo URL**: In this field, enter the URL where you have a square image saved. This image will appear to your users on various screens and pages.
-* **Support Email**: The email used to contact your support team.
-* **Support URL**: The link to your company/organization support page.
-
-Click **SAVE** when finished to submit your changes.
-
-### API Authorization Settings
-
-**Default Audience**: Allows you to specify an API Identifier for a default audience when using the [API Authorization](/api-auth) flows. The will cause all [Access Tokens](/tokens/access-token) issued by Auth0 to have this API Identitifier specified as an audience.
-
-::: note
-This setting is equivalent to appending the audience to every authorization request made to the tenant for every application. This will cause new behaviour that might result in breaking changes for some of your applications. Please contact support if you require assistance.
-:::
-
-**Default Directory**: Name of the connection to be use for [Password Grant exchanges](/api-auth/tutorials/password-grant). The __Default Directory__ value should be the exact name of an existing [connection](/connections) of one of the following strategies: `auth0-adldap`, `ad`, `auth0`, `email`, `sms`, `waad` or `adfs`.
-
-### Error Pages
-
-
-
-In the event of an authorization error, you may choose to display to your users either a generic error page or you can redirect users to your own customized error page.
-
-[Learn about Custom Error Pages](/hosted-pages/custom-error-pages).
-
-## Subscription and Payment
-
-
-
-The __Subscription__ tab allows you to review and change your current subscription and to move to another plan, as well as specify your billing details. You can learn more [about changing your Subscription](/support/subscription).
-
-## Active Users
-
-The __Active Users__ functionality has been moved to the [Quota Utilization Report](https://support.auth0.com/reports/quota) in the Support Center.
-
-## Dashboard Admins
-
-Allows you to add or remove administrators for your Auth0 tenant, as well as review whether administrators have Multifactor authentication enabled for their account. [Learn about Dashboard Admins](/tutorials/manage-dashboard-admins).
-
-## Webtasks
-
-The Auth0 rules engine uses [webtask.io](https://webtask.io/). This section explains about how to build apps and extensions on top of webtask.
-
-[Learn more about Webtasks](https://webtask.io/).
-
-## Advanced
-
-### Logout
-
-
-
-Allows you to specify the **Allowed Logout URLs** for your tenant. These are a set of URLs that are valid to redirect to after logout from Auth0 when no `client_id` is specified on the logout endpoint invocation. It's useful as a global list when SSO is enabled.
-
-Learn more about [Logout](/logout).
-
-### Session Timeout
-
-
-
-Allows you to specify the **SSO Cookie Timeout**. This value is the login session lifetime, which is how long the session will stay valid measured in minutes. The default value is 10080 minutes (or 7 days).
-
-This is the session timeout for the Auth0 session. You can configure separately the timeouts used with tokens issued by Auth0, such as the OpenID Connect ID Token expiration claim or the SAML lifetime assertions. These are often used to drive the sessions on the applications (SAML SPs) themselves and are independent of the Auth0 (IdP) session.
-
-Learn more about [Single Sign On](/sso/current).
-
-### Global Application Information
-
-
-
-The **Global Client ID** and **Global Client Secret** are used to generate tokens for legacy Auth0 APIs. Typically, you will not need these values. If you need to have the global client secret changed, please [contact support](https://support.auth0.com).
-
-### Settings
-
-**Change Password flow v2**: Turning this on enables a new version of the change password flow. The previous alternative has been deprecated and we strongly recommend enabling v2. This flag is presented only for backwards compatibility and once enabled you won't be able to disable it.
-
-You can configure how the Change Password widget will look like at the [Password Reset](${manage_url}/#/password_reset) tab inside the [Hosted Pages](${manage_url}/#/login_page) section of the dashboard.
-
-**Enable Application Connections**: This flag determines whether all current connections shall be enabled when a new [Application](${manage_url}/#/applications) is created.
diff --git a/articles/dashboard/guides/apis/add-permissions-apis.md b/articles/dashboard/guides/apis/add-permissions-apis.md
new file mode 100644
index 0000000000..5a2387069f
--- /dev/null
+++ b/articles/dashboard/guides/apis/add-permissions-apis.md
@@ -0,0 +1,57 @@
+---
+title: Add API Permissions
+description: Learn how to add permissions to APIs using the Auth0 Management Dashboard.
+topics:
+ - authorization
+ - dashboard
+ - RBAC
+ - scopes
+ - permissions
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Add API Permissions
+
+This guide will show you how to add permissions to an API using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/apis/update-permissions-apis).
+
+::: warning
+By default, any user of any application can ask for any permission defined here. You can implement access policies to limit this behavior via [Rules](/rules).
+:::
+
+1. Navigate to the [APIs](${manage_url}/#/apis) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the API to view.
+
+
+
+2. Click the **Permissions** tab, enter a permission name and description for the permission you want to add, and click **Add**.
+
+
+
+## Reserved names
+
+The following permission names are reserved and cannot be set as custom API permissions:
+
+* address
+* created_at
+* email
+* email_verified
+* family_name
+* given_name
+* identities
+* name
+* nickname
+* offline_access
+* openid
+* phone
+* picture
+* profile
+
+## Keep reading
+
+- [Customize the Consent Prompt](/scopes/current/guides/customize-consent-prompt)
+- [Represent Multiple APIs Using a Single Logical API in Auth0](/api-auth/tutorials/represent-multiple-apis)
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Enable Role-Based Access Control for APIs](/dashboard/guides/apis/enable-rbac)
diff --git a/articles/dashboard/guides/apis/delete-permissions-apis.md b/articles/dashboard/guides/apis/delete-permissions-apis.md
new file mode 100644
index 0000000000..5cf655a78b
--- /dev/null
+++ b/articles/dashboard/guides/apis/delete-permissions-apis.md
@@ -0,0 +1,34 @@
+---
+title: Delete API Permissions
+description: Learn how to delete permissions from APIs using the Auth0 Management Dashboard.
+topics:
+ - authorization
+ - dashboard
+ - RBAC
+ - scopes
+ - permissions
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Delete API Permissions
+
+This guide will show you how to delete permissions from an API using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/apis/update-permissions).
+
+1. Navigate to the [APIs](${manage_url}/#/apis) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the API to view.
+
+
+
+2. Click the **Permissions** tab, then click the trashcan icon next to the permission you want to remove, and confirm.
+
+
+
+## Keep reading
+
+- [How to Customize the Consent Prompt](/scopes/current/guides/customize-consent-prompt)
+- [How to Represent Multiple APIs Using a Single Logical API in Auth0](/api-auth/tutorials/represent-multiple-apis)
+- [Role-Based Access Control (RBAC)](/authorization/concepts/rbac)
+- [Enable Role-Based Access Control for APIs](/dashboard/guides/apis/enable-rbac)
\ No newline at end of file
diff --git a/articles/dashboard/guides/apis/enable-rbac.md b/articles/dashboard/guides/apis/enable-rbac.md
new file mode 100644
index 0000000000..c45e598467
--- /dev/null
+++ b/articles/dashboard/guides/apis/enable-rbac.md
@@ -0,0 +1,39 @@
+---
+title: Enable Role-Based Access Control for APIs
+description: Learn how to enable role-based access control (RBAC) for an API using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - roles
+ - rbac
+ - apis
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Enable Role-Based Access Control for APIs
+
+This guide will show you how to enable [role-based access control (RBAC)](/authorization/concepts/rbac) using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/apis/enable-rbac). This effectively enables the API Authorization Core feature set.
+
+1. Navigate to the [APIs](${manage_url}/#/apis) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the API to view.
+
+
+
+2. Scroll to **RBAC Settings** and enable the **Enable RBAC** toggle.
+
+
+
+3. If you want to include all permissions assigned to the user in the `permissions` claim of the Access Token, enable the **Add Permissions in the Access Token** toggle, and click **Save**.
+
+::: note
+Including permissions in the Access Token allows you to make minimal calls to retrieve permissions, but increases token size. As long as RBAC is enabled, the `scope` claim of the Access Token includes an intersection of the requested permissions and the permissions assigned to the user, regardless of whether permissions are also included in the Access Token.
+
+When RBAC is disabled, default behavior is observed; an application can request any permission defined for the API, and the `scope` claim will include all requested permissions.
+:::
+
+::: warning
+Remember that any configured [rules](/authorization/concepts/authz-rules) run _after_ the RBAC-based authorization decisions are made, so they may override default behavior.
+:::
diff --git a/articles/dashboard/guides/apis/update-token-lifetime.md b/articles/dashboard/guides/apis/update-token-lifetime.md
new file mode 100644
index 0000000000..44db6613d2
--- /dev/null
+++ b/articles/dashboard/guides/apis/update-token-lifetime.md
@@ -0,0 +1,37 @@
+---
+title: Update Access Token Lifetime
+description: Learn how to update the Access Token lifetime for an API using the Auth0 Dashboard.
+topics:
+ - applications
+ - access-token
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Update Access Token Lifetime
+
+You can change the Access Token lifetime using Auth0's Dashboard.
+
+1. Navigate to the [APIs](${manage_url}/#/apis) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the API to view.
+
+2. Locate the **Token Expiration (Seconds)** field, and enter the appropriate Access Token lifetime (in seconds) for the API.
+
+ ::: note
+ The **Token Expiration For Browser Flows (Seconds)** field refers to Access Tokens issued for the API via implicit and hybrid flows and does not cover all flows initiated from browsers. For example the PKCE flow (used in auth0-js-spa SDK) can be initiated from the browser, but it refers to the Token Expiration not the Token Expiration For Browser Flows value.
+ :::
+
+ 
+
+ Here are some examples of token expiration values:
+
+ | **Value** | **Description** |
+ |------------|-----------------|
+ | Default | 86400 seconds (24 hours) |
+ | Maximum | 2592000 seconds (30 days) |
+
+3. Click **Save Changes**.
+
diff --git a/articles/dashboard/guides/applications/_includes/_register-app-next-steps.md b/articles/dashboard/guides/applications/_includes/_register-app-next-steps.md
new file mode 100644
index 0000000000..24e1f21fca
--- /dev/null
+++ b/articles/dashboard/guides/applications/_includes/_register-app-next-steps.md
@@ -0,0 +1,19 @@
+::: note
+After creating your first application, you should [set the environment for your tenant](/dev-lifecycle/setting-up-env#set-the-environment). Options include development, staging, or production.
+:::
+
+## Next Steps
+
+Once you have registered and configured your Application, some common next steps are:
+
+- Configure a [Connection](/connections) and enable it for your Application
+
+- Modify your app code to use your Auth0-registered Application. See our [quickstarts](/quickstarts), where you'll find detailed instructions and samples for a variety of technologies. You'll also learn how to implement login and logout, handle your user sessions, retrieve and display user profile information, add [Rules](/rules) to customize your [authentication flow](/application-auth), and more.
+
+- Call an API using our [API Authorization](/api-auth) feature set.
+
+- Use [Auth0 APIs](/api/info).
+
+ - The [Authentication API](/api/authentication) handles all primary identity-related functions (for example: login, logout, get user profile). Most users consume this API through our [Quickstarts](/quickstarts), the [Auth0.js library](/libraries/auth0js), or the [Lock widget](/libraries/lock). However, if you are building all of your authentication UI manually, you will have to interact with this API directly.
+
+ - The [Management API](/api/management/v2) allows you to automate various tasks that can also be accessed via the Dashboard in Auth0 (for example: creating users, setting application grant types).
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/_includes/_register-app-part1.md b/articles/dashboard/guides/applications/_includes/_register-app-part1.md
new file mode 100644
index 0000000000..8003b553ab
--- /dev/null
+++ b/articles/dashboard/guides/applications/_includes/_register-app-part1.md
@@ -0,0 +1,5 @@
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}), and click **+ Create Application**.
+
+2. Enter a descriptive name for your Application, select ${application_type_create}, and click **Create**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/_includes/_register-app-part2-m2m.md b/articles/dashboard/guides/applications/_includes/_register-app-part2-m2m.md
new file mode 100644
index 0000000000..3338104ec6
--- /dev/null
+++ b/articles/dashboard/guides/applications/_includes/_register-app-part2-m2m.md
@@ -0,0 +1,5 @@
+Once the new ${application_type} Application is created, you will be redirected to the Application's settings. Available tabs include:
+
+* **Settings**: Shows all available [settings](/dashboard/reference/settings-application#advanced-settings) for your application. By default, most of the settings will be created for you.
+* **Quick Start**: Shows all the available examples for ${application_type} applications. It also shows you how you can call your API using various technologies. To learn how to accept and validate Access Tokens in your API, see our [Backend/API Quickstarts](/quickstart/backend).
+* **APIs**: Allows you to authorize additional APIs for use with your Application.
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/_includes/_register-app-part2.md b/articles/dashboard/guides/applications/_includes/_register-app-part2.md
new file mode 100644
index 0000000000..f26b21ba62
--- /dev/null
+++ b/articles/dashboard/guides/applications/_includes/_register-app-part2.md
@@ -0,0 +1,6 @@
+Once the new ${application_type} Application is created, you will be redirected to the Application's settings. Available tabs include:
+
+* **Settings**: Shows all available [settings](/dashboard/reference/settings-application#advanced-settings) for your application. By default, most of the settings will be created for you.
+* **Quick Start**: Shows all the available examples for ${application_type} applications.
+* **Add-ons**: Allows you to enable [Add-ons](/addons) for your Application. Add-ons are extensions and usually are third-party APIs used with Applications for which Auth0 generates Access Tokens.
+* **Connections**: Allows you to enable [Connections](/connections) for your Application. Connections are sources of users; they can be enabled and shared between multiple Applications.
diff --git a/articles/dashboard/guides/applications/enable-android-app-links.md b/articles/dashboard/guides/applications/enable-android-app-links.md
new file mode 100644
index 0000000000..9db6cbdf03
--- /dev/null
+++ b/articles/dashboard/guides/applications/enable-android-app-links.md
@@ -0,0 +1,65 @@
+---
+title: Enable Android App Links Support
+description: Learn how to enable Android App Links support for your Auth0 application using the Auth0 Dashboard.
+topics:
+ - applications
+ - android
+ - app-links
+ - dashboard
+contentType: how-to
+useCase:
+ - build-an-app
+ - enable-mobile-auth
+---
+# Enable Android App Links Support
+
+[Android App Links](https://developer.android.com/training/app-links/index.html) allow an application to designate itself as the default handler of a given type of link. For example, clicking a URL in an email would open the link in the designated application. This guide will show you how to enable Android App links support for your Auth0-registered application using Auth0's Dashboard.
+
+## Provide Your App's Package Name and Certificate Fingerprint
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}), and click the name of the Application to view.
+
+
+
+2. Scroll to the bottom of the **Settings** page, and click **Show Advanced Settings**.
+
+
+
+3. Select the **Device Settings** tab, provide the [App Package Name](https://developer.android.com/studio/build/application-id.html) and the SHA256 fingerprints of your app’s signing certificate for your Android application, and click **Save Changes**.
+
+You can use the following command to generate the fingerprint using the Java keytool in your terminal:
+
+```bash
+keytool -list -v -keystore my-release-key.keystore
+```
+
+::: note
+For more info about signing certificates, see Android's [Sign Your App](https://developer.android.com/studio/publish/app-signing.html) developer doc.
+:::
+
+
+
+
+## Test Your App Link
+
+1. Navigate to the following URL in your browser:
+
+`https://${account.namespace}/.well-known/assetlinks.json`
+
+If the link is successful, you will return the following JSON (formatted for readability):
+
+```json
+[{
+ "relation": ["delegate_permission/common.handle_all_urls"],
+ "target": {
+ "namespace": "android_app",
+ "package_name": "com.mycompany.app1",
+ "sha256_cert_fingerprints":
+ ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
+ }
+}]
+```
+
+::: note
+For more info about testing your app link, see Android's [Verify Android App Links](https://developer.android.com/training/app-links/verify-site-associations.html#testing) developer doc.
+:::
diff --git a/articles/dashboard/guides/applications/enable-sso-app.md b/articles/dashboard/guides/applications/enable-sso-app.md
new file mode 100644
index 0000000000..a2877d7ec3
--- /dev/null
+++ b/articles/dashboard/guides/applications/enable-sso-app.md
@@ -0,0 +1,31 @@
+---
+title: Enable Single Sign-On for Applications
+description: Learn how to enable Single Sign-on (SSO) for an application using the Auth0 Management Dashboard. Only for use with legacy tenants.
+toc: true
+topics:
+ - sso
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - integrate-saas-sso
+ - configure-sso
+ - build-an-app
+---
+# Enable Single Sign-On for Applications
+
+By default, seamless Single Sign-on (SSO) is enabled for all new Auth0 tenants; however, **legacy tenants** may [choose whether to enable this feature at the tenant level](/dashboard/guides/tenants/enable-sso-tenant). If you have not enabled tenant-level SSO, you may enable it per application.
+
+This guide will show you how to enable Single Sign-On (SSO) for your application using Auth0's Dashboard.
+
+::: warning
+Before enabling SSO for an [application](/applications), you must first create and configure a connection for each [Identity Provider](/identityproviders) you want to use. For social identity providers, make sure the connection is not using [developer keys](/connections/social/devkeys) if you use the [Classic Universal Login Experience](/universal-login/classic).
+:::
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the application to view.
+
+
+
+2. Scroll to the bottom of the Settings page, locate **Use Auth0 instead of the IdP to do Single Sign-on**, enable the toggle, and click **Save Changes**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/enable-universal-links.md b/articles/dashboard/guides/applications/enable-universal-links.md
new file mode 100644
index 0000000000..d0e23998b9
--- /dev/null
+++ b/articles/dashboard/guides/applications/enable-universal-links.md
@@ -0,0 +1,63 @@
+---
+title: Enable Universal Links Support in Apple Xcode
+description: Learn how to enable universal links support for your Auth0 app in Apple Xcode using the Auth0 Dashboard.
+topics:
+ - applications
+ - ios
+ - universal-links
+ - dashboard
+contentType: how-to
+useCase:
+ - build-an-app
+ - enable-mobile-auth
+---
+# Enable Universal Links Support in Apple Xcode
+
+Universal links establish a *verified relationship between domains and applications*, so both your Auth0 Application settings and your iOS application need to be in sync. To do this, you need to provide Auth0 with the following information:
+
+* `Team ID`;
+* `Bundle identifier`.
+
+This guide will show you how to enable universal links support for your Auth0-registered application using Auth0's Dashboard.
+
+## Find Your Apple `Team ID` and `Bundle Identifier`
+
+To find your Apple `Team ID`, go to your [Apple developer account summary page](https://developer.apple.com/membercenter/index.action#accountSummary).
+
+To find your iOS application's `Bundle identifier`, go to its [Xcode project settings](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/ConfiguringYourApp/ConfiguringYourApp.html) page:
+
+
+
+## Provide Your Apple `Team ID` and `Bundle Identifier` to Auth0
+
+1. Navigate to the [Applications](${manage_url}/#/clients) page of the [Auth0 Dashboard](${manage_url}), and click the name of the Application to view.
+
+
+
+2. Scroll to the bottom of the *Settings* page, and click *Show Advanced Settings.*
+
+
+
+3. Select the *Device Settings* tab, provide the **Team ID** and the **App bundler identifier** values for your iOS application, and click **Save Changes**.
+
+
+
+## Test Your Universal Link
+
+To check whether the universal links `apple-app-site-association` file is available for your application, navigate to the following URL in your browser:
+
+`${account.namespace}/apple-app-site-association`.
+
+If the link is successful, you will see the following JSON (formatted for readability):
+
+```json
+{
+ "applinks": {
+ "apps": [],
+ "details": [{
+ "appID": "86WQXF56BC.com.auth0.Passwordless-Email",
+ "paths": ["/ios/com.auth0.Passwordless-Email/*"]
+ }]
+ }
+}
+```
diff --git a/articles/dashboard/guides/applications/register-app-m2m.md b/articles/dashboard/guides/applications/register-app-m2m.md
new file mode 100644
index 0000000000..2420df9da6
--- /dev/null
+++ b/articles/dashboard/guides/applications/register-app-m2m.md
@@ -0,0 +1,37 @@
+---
+title: Register Machine-to-Machine Applications
+description: Learn how to register and configure a machine-to-machine (M2M) application using the Auth0 Management Dashboard. These may include non-interactive applications, such as command-line tools, daemons, IoT devices, or services running on your back-end.
+topics:
+ - applications
+ - m2m
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - call-api
+---
+# Register Machine-to-Machine Applications
+
+To integrate Auth0 with a [machine-to-machine (M2M) application](/applications), you must first register your app with Auth0. This guide will show you how to register an M2M application using Auth0's Dashboard.
+
+::: note
+M2M applications are linked to an API and its [scopes](/scopes/current/api-scopes), which are selected from pre-defined values. Make sure you have already [registered the associated API](/apis#how-to-configure-an-api-in-auth0) with Auth0 and [defined scopes for the API](scopes/current#define-scopes-using-the-dashboard) before beginning this guide.
+
+If you want to authorize your application to access only Auth0's [Management API](/api/info#management-api-v2), you do not need to do anything; the Management API is pre-populated for you.
+:::
+
+<%= include('./_includes/_register-app-part1', { application_type: 'M2M', application_type_create: 'Machine-to-Machine App' }) %>
+
+3. Select the API you want to be able to call from your Application.
+
+
+
+4. Select the [scopes](/scopes/current/api-scopes) you want to be issued as part of your Application's Access Token, and click **Authorize**.
+
+
+
+<%= include('./_includes/_register-app-part2-m2m', { application_type: 'M2M', application_type_create: 'Machine-to-Machine App' }) %>
+
+<%= include('./_includes/_register-app-next-steps') %>
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/register-app-native.md b/articles/dashboard/guides/applications/register-app-native.md
new file mode 100644
index 0000000000..591ab3d0eb
--- /dev/null
+++ b/articles/dashboard/guides/applications/register-app-native.md
@@ -0,0 +1,31 @@
+---
+title: Register Native Applications
+description: Learn how to register and configure a native application using the Auth0 Management Dashboard. These may include mobile, desktop, or hybrid apps running natively in a device (e.g., i0S, Android).
+topics:
+ - applications
+ - native-app
+ - mobile-app
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - call-api
+---
+# Register Native Applications
+
+To integrate Auth0 with a [native application](/applications), you must first register your app with Auth0. This guide will show you how to register a native application using Auth0's Dashboard.
+
+<%= include('./_includes/_register-app-part1', { application_type: 'native', application_type_create: 'Native App' }) %>
+
+<%= include('./_includes/_register-app-part2', { application_type: 'native', application_type_create: 'Native App' }) %>
+
+3. If you're developing a mobile app, provide the necessary iOS/Android parameters in the **Advanced Settings** area, and click **Save Changes**.
+
+- For iOS apps, [provide your **Team ID** and **App Bundle Identifier**](/dashboard/guides/applications/enable-universal-links).
+
+- For Android apps, [provide your **App Package Name** and your **Key Hashes**](/dashboard/guides/applications/enable-android-app-links).
+
+<%= include('./_includes/_register-app-next-steps') %>
+
diff --git a/articles/dashboard/guides/applications/register-app-regular-web.md b/articles/dashboard/guides/applications/register-app-regular-web.md
new file mode 100644
index 0000000000..f7fdc55ca8
--- /dev/null
+++ b/articles/dashboard/guides/applications/register-app-regular-web.md
@@ -0,0 +1,25 @@
+---
+title: Register Regular Web Applications
+description: Learn how to register and configure a regular web application using the Auth0 Management Dashboard. These may include traditional web applications that perform most of their application logic on the server (e.g., Express.js, ASP.NET).
+topics:
+ - applications
+ - regular-web-app
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - call-api
+---
+# Register Regular Web Applications
+
+To integrate Auth0 with a [regular web app](/applications), you must first register your app with Auth0. This guide will show you how to register a regular web application using Auth0's Dashboard.
+
+<%= include('./_includes/_register-app-part1', { application_type: 'regular web', application_type_create: 'Regular Web App' }) %>
+
+<%= include('./_includes/_register-app-part2', { application_type: 'regular web', application_type_create: 'Regular Web App' }) %>
+
+3. Scroll down and locate the **Trust Token Endpoint IP Header** setting, enable it, and click **Save Changes**. When enabled, this protects against brute-force attacks.
+
+<%= include('./_includes/_register-app-next-steps') %>
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/register-app-spa.md b/articles/dashboard/guides/applications/register-app-spa.md
new file mode 100644
index 0000000000..cb411d7a50
--- /dev/null
+++ b/articles/dashboard/guides/applications/register-app-spa.md
@@ -0,0 +1,22 @@
+---
+description: Learn how to register and configure a Single-Page Application (SPA) using the Auth0 Management Dashboard. These may include JavaScript applications that perform most of their user interface logic in a web browser, communicating with a web server primarily using APIs (e.g., AngularJS + Node.js, React).
+topics:
+ - applications
+ - single-page-app
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - call-api
+---
+# Register Single-Page Applications
+
+To integrate Auth0 with a [single-page app](/applications), you must first register your app with Auth0. This guide will show you how to register a single-page application using Auth0's Dashboard.
+
+<%= include('./_includes/_register-app-part1', { application_type: 'single-page', application_type_create: 'Single-Page Web App' }) %>
+
+<%= include('./_includes/_register-app-part2', { application_type: 'single-page', application_type_create: 'Single-Page Web App' }) %>
+
+<%= include('./_includes/_register-app-next-steps') %>
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/remove-app.md b/articles/dashboard/guides/applications/remove-app.md
new file mode 100644
index 0000000000..fa7b667d50
--- /dev/null
+++ b/articles/dashboard/guides/applications/remove-app.md
@@ -0,0 +1,25 @@
+---
+title: Remove Application
+description: Learn how to remove an Auth0-registered application using the Auth0 Management Dashboard.
+toc: false
+topics:
+ - applications
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+ - call-api
+---
+# Remove Application
+
+This guide will show you how to remove an application using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/applications/remove-app).
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}), and click the name of the Application to view.
+
+
+
+2. Scroll to the bottom of the **Settings** page, locate the *Danger Zone*, click **Delete Application**, and confirm. Once confirmed, this operation cannot be undone.
+
+
diff --git a/articles/dashboard/guides/applications/rotate-client-secret.md b/articles/dashboard/guides/applications/rotate-client-secret.md
new file mode 100644
index 0000000000..4e97711caf
--- /dev/null
+++ b/articles/dashboard/guides/applications/rotate-client-secret.md
@@ -0,0 +1,33 @@
+---
+title: Rotate Client Secret
+description: Learn how to rotate an application's client secret using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - client-secrets
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# Rotate Client Secret
+
+This guide will show you how to change an application's client secret using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/applications/rotate-client-secret).
+
+::: note
+The global client secret can also be rotated via the Dashboard. Your global client ID and secret can be found in your [Advanced Tenant Settings](${manage_url}/#/tenant/advanced).
+:::
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Scroll to the bottom of the Application Settings page and under **Danger Zone**, you will see the Rotate secret option. Click the **Rotate** button to rotate the client's secret.
+
+
+
+You can view your new secret by selecting the **Reveal client secret** checkbox.
+
+3. Update authorized applications
+
+After you rotate your client secret, you must update any authorized applications with the new value.
diff --git a/articles/dashboard/guides/applications/set-up-addon-saml2-aws.md b/articles/dashboard/guides/applications/set-up-addon-saml2-aws.md
new file mode 100644
index 0000000000..4b152aeae2
--- /dev/null
+++ b/articles/dashboard/guides/applications/set-up-addon-saml2-aws.md
@@ -0,0 +1,47 @@
+---
+title: Set Up the SAML2 Web App Add-On with AWS for Applications
+description: Learn how to set up the SAML2 Web App add-ons with Amazon Web Services (AWS) for an application registered with Auth0 using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - add-ons
+ - AWS
+ - SAML
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - integrate-third-party-apps
+---
+# Set Up the SAML2 Web App Add-On with AWS for Applications
+
+This guide will show you how to set up the SAML2 Web App [add-on](/addons) with Amazon Web Services (AWS) for an application using Auth0's Dashboard.
+
+::: warning
+This is just one step in the process of integrating Auth0 with AWS. For complete steps, choose an integration from [Integrate Auth0 with Amazon Web Services (AWS)](/integrations/aws).
+:::
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to update.
+
+2. Click **Add-ons**, and enable the toggle for the **SAML2 Web App** add-on.
+
+3. Locate **Application Callback URL** and enter `https://signin.aws.amazon.com/saml`, then paste the following SAML configuration code into **Settings**, then click **Enable**.
+
+```js
+{
+ "audience": "https://signin.aws.amazon.com/saml",
+ "mappings": {
+ "email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
+ "name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
+ },
+ "createUpnClaim": false,
+ "passthroughClaimsWithNoMapping": false,
+ "mapUnknownClaimsAsIs": false,
+ "mapIdentities": false,
+ "nameIdentifierFormat": "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
+ "nameIdentifierProbes": [
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
+ ]
+}
+```
+
+4. Click the **Usage** tab, locate **Identity Provider Metadata**, and download the metadata file. You'll need this when you configure Auth0 as the identity provider (IdP) for AWS in the next step.
diff --git a/articles/dashboard/guides/applications/set-up-addons.md b/articles/dashboard/guides/applications/set-up-addons.md
new file mode 100644
index 0000000000..b88a678135
--- /dev/null
+++ b/articles/dashboard/guides/applications/set-up-addons.md
@@ -0,0 +1,37 @@
+---
+title: Set Up Add-ons
+description: Learn how to set up add-ons, like Amazon Web Services and Azure Blob Storage, for an application registered with Auth0 using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - add-ons
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - integrate-third-party-apps
+---
+# Set Up Add-ons
+
+<%= include('../../../_includes/_uses-delegation') %>
+
+This guide will show you how to set up an [add-on](/addons) for an application using Auth0's Dashboard.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Click **Add-ons**, and enable the toggle for the add-on you want to set up.
+
+
+
+Each integration is different and requires different parameters and configuration. Once the add-on is activated, you will see tailored instructions with details on how to integrate with it.
+
+For more info about using Auth0 to authenticate and authorize add-ons, see:
+- [Azure Blob Storage](/addons/azure-blob-storage)
+- [Azure Mobile Services](/addons/azure-mobile-services)
+- [Azure Service Bus](/addons/azure-sb)
+- [Salesforce (sandbox)](/addons/salesforce-sandbox)
+- [Salesforce](/addons/salesforce)
+- [SAP OData](/addons/sap-odata)
+
+For more info on how to use delegation with the Amazon Web Services (AWS) API Gateway, see the [AWS API Gateway Tutorial](/integrations/aws-api-gateway/delegation).
\ No newline at end of file
diff --git a/articles/dashboard/guides/applications/set-up-cors.md b/articles/dashboard/guides/applications/set-up-cors.md
new file mode 100644
index 0000000000..a8773f13ba
--- /dev/null
+++ b/articles/dashboard/guides/applications/set-up-cors.md
@@ -0,0 +1,27 @@
+---
+title: Set Up Cross-Origin Resource Sharing (CORS)
+description: Learn how to set up Cross-Origin Resource Sharing (CORS) for an application registered with Auth0 using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - cors
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-app
+---
+# Set Up Cross-Origin Resource Sharing (CORS)
+
+::: warning
+Auth0 strongly recommends that authentication transactions be handled via [Universal Login](/universal-login). Doing so offers the easiest and most secure way to authenticate users. However, some situations may require that login be directly embedded in an application. When embedded login is required, an application must be set up for cross-origin resource sharing (CORS).
+:::
+
+This guide will show you how to set up cross-origin resource sharing (CORS) for an application using Auth0's Dashboard.
+
+For security purposes, your app's origin URL must be listed as an approved URL. If you have not already added it to the **Allowed Callback URLS** for your application, you will need to add it to the list of **Allowed Origins (CORS)**.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Scroll down and locate **Allowed Origins (CORS)**, enter your app's [origin URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin), and click **Save Changes**.
diff --git a/articles/dashboard/guides/applications/update-app-connections.md b/articles/dashboard/guides/applications/update-app-connections.md
new file mode 100644
index 0000000000..7ad369dcfd
--- /dev/null
+++ b/articles/dashboard/guides/applications/update-app-connections.md
@@ -0,0 +1,20 @@
+---
+title: Update Application Connections
+description: Learn how to update an application's enabled connections using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - connections
+ - dashboard
+contentType: how-to
+useCase:
+ - build-an-app
+---
+# Update Application Connections
+
+This guide will show you how to change your application's enabled connections using Auth0's Dashboard.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Click the **Connections** tab, and enable or disable the appropriate connections for the application.
diff --git a/articles/dashboard/guides/applications/update-grant-types.md b/articles/dashboard/guides/applications/update-grant-types.md
new file mode 100644
index 0000000000..6a3ad79181
--- /dev/null
+++ b/articles/dashboard/guides/applications/update-grant-types.md
@@ -0,0 +1,40 @@
+---
+title: Update Grant Types
+description: Learn how to update an application's grant types using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - grant-types
+ - dashboard
+contentType: how-to
+useCase:
+ - build-an-app
+---
+# Update Grant Types
+
+This guide will show you how to change your application's grant types using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/applications/update-grant-types).
+
+::: warning
+As of 8 June 2017, new Auth0 customers **cannot** add legacy grant types to their Applications. Customers as of 8 June 2017 can add legacy grant types to only their existing Applications.
+:::
+
+::: panel Troubleshooting
+* The device code grant type is only available for native apps.
+
+* Attempting to use a flow with an Application lacking the appropriate `grant_types` for that flow (or with the field empty) will result in the following error:
+
+```text
+Grant type `grant_type` not allowed for the client.
+```
+:::
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Scroll to the bottom of the page, and click **Advanced Settings**.
+
+
+
+3. Click the **Grant Types** tab, and enable or disable the appropriate grants for the application. When finished, click **Save Changes**.
+
+
diff --git a/articles/dashboard/guides/applications/update-signing-algorithm.md b/articles/dashboard/guides/applications/update-signing-algorithm.md
new file mode 100644
index 0000000000..3011b2493a
--- /dev/null
+++ b/articles/dashboard/guides/applications/update-signing-algorithm.md
@@ -0,0 +1,28 @@
+---
+title: Update the Signing Algorithm for an Application
+description: Learn how to update an application's signing algorithm using the Auth0 Dashboard.
+toc: true
+topics:
+ - tokens
+ - id-tokens
+ - signing-algorithms
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - invoke-api
+---
+# Update the Signing Algorithm for an Application
+
+This guide will show you how to change your application's [signing algorithm](/tokens/concepts/signing-algorithms) using Auth0's Dashboard.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Scroll to the bottom of the page, click **Advanced Settings**, and click the **OAuth** tab.
+
+
+
+3. Locate **JsonWebToken Signature Algorithm**, and select the appropriate signing algorithm for the application. When finished, click **Save Changes**.
diff --git a/articles/dashboard/guides/applications/update-token-lifetime.md b/articles/dashboard/guides/applications/update-token-lifetime.md
new file mode 100644
index 0000000000..cd79494dfc
--- /dev/null
+++ b/articles/dashboard/guides/applications/update-token-lifetime.md
@@ -0,0 +1,24 @@
+---
+title: Update ID Token Lifetime
+description: Learn how to update the ID token lifetime for an application using the Auth0 Dashboard.
+topics:
+ - applications
+ - id-token
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - add-login
+---
+# Update ID Token Lifetime
+
+You can change the ID Token lifetime using Auth0's Dashboard.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Scroll to the bottom of the Application Settings page, locate the **ID Token Expiration** field, and enter the appropriate ID Token lifetime (in seconds) for the application. When finished, click **Save Changes**.
+
+
diff --git a/articles/dashboard/guides/applications/view-addons.md b/articles/dashboard/guides/applications/view-addons.md
new file mode 100644
index 0000000000..cb93b08916
--- /dev/null
+++ b/articles/dashboard/guides/applications/view-addons.md
@@ -0,0 +1,25 @@
+---
+title: View Add-ons
+description: Learn how to view available and configured add-ons for an application registered with Auth0 using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - add-ons
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - integrate-third-party-apps
+---
+
+# View Add-ons
+
+This guide will show you how to view all of the available and configured [add-ons](/addons) for an application using Auth0's Dashboard.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+2. Click **Add-ons**.
+
+
diff --git a/articles/dashboard/guides/applications/view-app-type-confidential-public.md b/articles/dashboard/guides/applications/view-app-type-confidential-public.md
new file mode 100644
index 0000000000..6f46d90493
--- /dev/null
+++ b/articles/dashboard/guides/applications/view-app-type-confidential-public.md
@@ -0,0 +1,35 @@
+---
+title: View Application Type - Confidential or Public
+description: Learn how to check whether an application is registered with Auth0 as a confidential or public app using the Auth0 Management Dashboard.
+topics:
+ - applications
+ - application-types
+ - dashboard
+contentType: how-to
+useCase:
+ - build-an-app
+---
+# View Application Type: Confidential or Public
+
+This guide will show you how to use Auth0's Dashboard to check whether an application is registered with Auth0 as a [confidential or public application](/applications/concepts/app-types-confidential-public).
+
+Auth0 determines this based on the **Token Endpoint Authentication Method** setting, which defines how an application authenticates against the [token endpoint](/api/authentication#get-token).
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Application to view.
+
+
+
+3. Locate the **Token Endpoint Authentication Method**.
+
+Its valid values are:
+
+* `None`, for a public application without a client secret
+* `Post`, for an application using HTTP POST parameters
+* `Basic`, for an application using HTTP Basic parameters
+
+These values map to confidential and public applications as follows:
+
+| Application Type | Token Endpoint Authentication Method |
+| - | - |
+| Public | **None** |
+| Confidential | **Basic**, **Post**, unspecified |
diff --git a/articles/dashboard/guides/connections/configure-connection-sync.md b/articles/dashboard/guides/connections/configure-connection-sync.md
new file mode 100644
index 0000000000..3b0c41a15a
--- /dev/null
+++ b/articles/dashboard/guides/connections/configure-connection-sync.md
@@ -0,0 +1,36 @@
+---
+title: Configure Connection Sync with Auth0
+description: Learn how to allow updates to the Auth0 normalized user profile from a connection using the Auth0 Dashboard.
+topics:
+ - connections
+ - identity-providers
+ - user-profile
+ - dashboard
+contentType: how-to
+useCase:
+ - build-an-app
+ - customize-connections
+ - manage-users
+---
+
+# Configure Connection Sync with Auth0
+
+This guide will show you how to update connection preferences for an upstream [Identity Provider](/connections) to control when updates to user profile root attributes will be allowed using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/connections/configure-connection-sync).
+
+::: warning
+<%= include('../../../_includes/_users_update_normalized_profile_attributes') %>
+:::
+
+1. Navigate to the [Auth0 Dashboard](${manage_url}/#/), and click **Authentication** in the left nav.
+
+2. Select a connection type:
+
+- [Database](${manage_url}/#/connections/database)
+- [Social](${manage_url}/#/connections/social)
+- [Enterprise](${manage_url}/#/connections/enterprise)
+
+3. Click the name of a connection to see its settings.
+
+4. Toggle **Sync user profile attributes at each login** to the desired setting, and click **Save**.
+
+ 
\ No newline at end of file
diff --git a/articles/dashboard/guides/connections/disable-cache-ad-ldap.md b/articles/dashboard/guides/connections/disable-cache-ad-ldap.md
new file mode 100644
index 0000000000..1f3793be92
--- /dev/null
+++ b/articles/dashboard/guides/connections/disable-cache-ad-ldap.md
@@ -0,0 +1,20 @@
+---
+title: Disable Credential Caching
+description: Learn how to disable credential caching at the connection level for an AD/LDAP enterprise connection using the Auth0 Management Dashboard.
+topics:
+ - connections
+ - dashboard
+ - ad-ldap
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Disable Credential Caching
+
+This guide will show you how to disable credential caching at the [connection](/identityproviders) level for an [AD/LDAP connection](/connector/overview) using Auth0's Dashboard.
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and click the **Active Directory/LDAP** connection.
+
+2. Enable the **Disable Cache** switch.
\ No newline at end of file
diff --git a/articles/dashboard/guides/connections/enable-connections-enterprise.md b/articles/dashboard/guides/connections/enable-connections-enterprise.md
new file mode 100644
index 0000000000..bebe428379
--- /dev/null
+++ b/articles/dashboard/guides/connections/enable-connections-enterprise.md
@@ -0,0 +1,32 @@
+---
+description: Learn how to enable enterprise connections for applications using the Auth0 Management Dashboard.
+topics:
+ - connections
+ - dashboard
+ - enterprise
+ - applications
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Enable Enterprise Connections
+
+This guide will show you how to enable enterprise [connections](/connections) for applications using Auth0's Dashboard.
+
+::: warning
+To enable your enterprise connection, you should have already [set it up](/connections/identity-providers-enterprise).
+:::
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and click on the connection type to view.
+
+ 
+
+2. Select the name of the connection to view.
+
+ 
+
+3. Select the **Applications** view, and enable or disable the connection for the appropriate application(s).
+
+ 
diff --git a/articles/dashboard/guides/connections/set-up-connections-database.md b/articles/dashboard/guides/connections/set-up-connections-database.md
new file mode 100644
index 0000000000..857764b819
--- /dev/null
+++ b/articles/dashboard/guides/connections/set-up-connections-database.md
@@ -0,0 +1,32 @@
+---
+description: Learn how to set up database connections for applications using the Auth0 Management Dashboard.
+topics:
+ - connections
+ - dashboard
+ - database
+ - configuration
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Set Up Database Connections
+
+This guide will show you how to set up database [connections](/connections) for applications using Auth0's Dashboard. The configured database connections can be used to log in to your application.
+
+1. Navigate to [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database), and select **+ Create DB Connection**.
+
+ 
+
+2. Enter a name for your connection, and select **Create**.
+
+ 
+
+3. Select the **Applications** view, enable the switch for each of your Auth0 applications that should be able to use this connection, and select **Save**.
+
+ 
+
+## Keep reading
+
+- [Test Database Connections](/dashboard/guides/connections/test-connections-database)
diff --git a/articles/dashboard/guides/connections/set-up-connections-social.md b/articles/dashboard/guides/connections/set-up-connections-social.md
new file mode 100644
index 0000000000..083069b3e0
--- /dev/null
+++ b/articles/dashboard/guides/connections/set-up-connections-social.md
@@ -0,0 +1,39 @@
+---
+description: Learn how to set up social connections for applications using the Auth0 Management Dashboard.
+topics:
+ - connections
+ - dashboard
+ - social
+ - configuration
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Set Up Social Connections
+
+This guide will show you how to set up social [connections](/connections) for applications using Auth0's Dashboard. The configured social connections can be used to log in to your application.
+
+::: warning
+You should already have set up credentials for your application in the social identity provider with which you want to allow users to log in to your application. To learn how to do so, select your identity provider from our list of [social connections](/connections#social).
+:::
+
+1. Navigate to [Auth0 Dashboard > Authentication > Social](${manage_url}/#/connections/social), and select **Create Connection**.
+
+2. Choose the connection you want to set up.
+
+3. Copy and paste the `Client ID` and `Client Secret` from your social identity provider, select the **Attributes** (and **Permissions**, where applicable), and click **Save**.
+
+ * **Attributes**: User data you want your app to be able to access.
+ * **Permissions**: Features you want your app to be able to access on the user's behalf.
+
+ 
+
+4. Select the **Applications** view, enable the switch for each of your Auth0 applications that should be able to use this connection, and select **Save**.
+
+ 
+
+## Keep reading
+
+- [Test Social Connections](/dashboard/guides/connections/test-connections-social)
diff --git a/articles/dashboard/guides/connections/test-connections-database.md b/articles/dashboard/guides/connections/test-connections-database.md
new file mode 100644
index 0000000000..3036272a53
--- /dev/null
+++ b/articles/dashboard/guides/connections/test-connections-database.md
@@ -0,0 +1,28 @@
+---
+description: Learn how to test database connections for applications using the Auth0 Management Dashboard.
+topics:
+ - connections
+ - dashboard
+ - database
+ - testing
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Test Database Connections
+
+This guide will show you how to test database [connections](/connections) for applications using Auth0's Dashboard. The configured database connections can be used to log in to your application.
+
+::: warning
+To properly test, you should have already [set up your database connection](/dashboard/guides/connections/set-up-connections-database) and [created a user](/dashboard/guides/users/create-users) for your database connection.
+:::
+
+1. Navigate to [Auth0 Dashboard > Authentication > Database](${manage_url}/#/connections/database), and select the Try arrow next to the connection you want to test.
+
+ 
+
+2. Enter your test user's username and password. If you have configured everything correctly, you will see the **It Works!** page:
+
+ 
\ No newline at end of file
diff --git a/articles/dashboard/guides/connections/test-connections-enterprise.md b/articles/dashboard/guides/connections/test-connections-enterprise.md
new file mode 100644
index 0000000000..1ff7ce8a7d
--- /dev/null
+++ b/articles/dashboard/guides/connections/test-connections-enterprise.md
@@ -0,0 +1,32 @@
+---
+description: Learn how to test enterprise connections for applications using the Auth0 Management Dashboard.
+topics:
+ - connections
+ - dashboard
+ - enterprise
+ - testing
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Test Enterprise Connections
+
+This guide will show you how to test enterprise [connections](/connections) for applications using Auth0's Dashboard.
+
+::: warning
+To properly test, you should have already [set up your enterprise connection](/connections/identity-providers-enterprise).
+:::
+
+1. Navigate to [Auth0 Dashboard > Authentication > Enterprise](${manage_url}/#/connections/enterprise), and select the connection type to view.
+
+ 
+
+2. Select the Try arrow next to the connection you want to test.
+
+ 
+
+3. Log in and consent to allow access to your app. If you have configured everything correctly, you will see the **It Works!** page.
+
+ 
diff --git a/articles/dashboard/guides/connections/test-connections-social.md b/articles/dashboard/guides/connections/test-connections-social.md
new file mode 100644
index 0000000000..011b80a3a4
--- /dev/null
+++ b/articles/dashboard/guides/connections/test-connections-social.md
@@ -0,0 +1,28 @@
+---
+description: Learn how to test social connections for applications using the Auth0 Management Dashboard.
+topics:
+ - connections
+ - dashboard
+ - social
+ - testing
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# Test Social Connections
+
+This guide will show you how to test social [connections](/connections) for applications using Auth0's Dashboard. The configured social connections can be used to log in to your application.
+
+::: warning
+To properly test, you should have already [set up your social connection](/dashboard/guides/connections/set-up-connections-social).
+:::
+
+1. Navigate to [Auth0 Dashboard > Authentication > Social](${manage_url}/#/connections/social), locate the connection you want to test, expand the More Options menu (**...**), and select **Try Connection**.
+
+ 
+
+2. Log in and consent to allow access to your app. If you have configured everything correctly, you will see the **It Works!** page:
+
+ 
diff --git a/articles/dashboard/guides/connections/view-connections.md b/articles/dashboard/guides/connections/view-connections.md
new file mode 100644
index 0000000000..24b6f76229
--- /dev/null
+++ b/articles/dashboard/guides/connections/view-connections.md
@@ -0,0 +1,33 @@
+---
+title: View Connections
+description: Learn how to view enabled connections in the Auth0 Management Dashboard.
+crews: crew-2
+topics:
+ - applications
+ - connections
+ - dashboard
+contentType: how-to
+useCase:
+ - build-an-app
+ - customize-connections
+---
+# View Connections
+
+This guide will show you how to view all of the available and configured [connections](/connections) using Auth0's Dashboard. The configured connections can be used to log in to your applications.
+
+1. Navigate to the [Auth0 Dashboard](${manage_url}/#/), and select **Authentication** in the left nav.
+
+2. Select a connection type:
+
+- [Database](${manage_url}/#/connections/database)
+- [Social](${manage_url}/#/connections/social)
+- [Enterprise](${manage_url}/#/connections/enterprise)
+- [Passwordless](${manage_url}/#/connections/passwordless)
+
+
+## Keep reading
+
+- [Set Up Social Connections](/dashboard/guides/connections/set-up-connections-social)
+- [Identity Providers Supported by Auth0](/identityproviders)
+- [Create Multiple Tenants](/dashboard/guides/tenants/create-multiple-tenants)
+- [Using Auth0 with Multi-Tenant Applications](/design/using-auth0-with-multi-tenant-apps)
\ No newline at end of file
diff --git a/articles/dashboard/guides/extensions/delegated-admin-create-app.md b/articles/dashboard/guides/extensions/delegated-admin-create-app.md
new file mode 100644
index 0000000000..ffa2b3bae3
--- /dev/null
+++ b/articles/dashboard/guides/extensions/delegated-admin-create-app.md
@@ -0,0 +1,57 @@
+---
+description: Learn how to create an application to use with the Delegated Admin Extension, which allows you to expose the Users section of the Auth0 Dashboard to a select group of users without allowing them access to the rest of the Dashboard.
+topics:
+ - extensions
+ - delegated-admin
+ - dae
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - create-delegated-admin-application
+---
+# Create Delegated Admin Applications
+
+Use the [Delegated Admin Extension](/extensions/delegated-admin), which allows you to expose the Users section of the Auth0 Dashboard to a select group of users without allowing them access to the rest of the Dashboard.
+
+Before you [add the Delegated Admin extension](/dashboard/guides/extensions/delegated-admin-install-extension), you need to create the Delegated Admin application in Auth0.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click **+Create Application**.
+
+2. Enter a descriptive name for your Application (for example, *Users Dashboard*), select an application type of **Single-Page Web Application**, and click **Create**.
+
+3. On the **Settings** tab, set the **Allowed Callback URLs** and **Allowed Logout URLs** based on your location, and click **Save Changes**:
+
+ If you are using Node 8:
+
+ | Location | Allowed Callback URL |
+ | --------- | -------------------- |
+ | USA | `https://${account.tenant}.us8.webtask.io/auth0-delegated-admin/login` |
+ | Europe | `https://${account.tenant}.eu8.webtask.io/auth0-delegated-admin/login` |
+ | Australia | `https://${account.tenant}.au8.webtask.io/auth0-delegated-admin/login` |
+
+ | Location | Allowed Logout URL |
+ | --------- | ------------------ |
+ | USA | `https://${account.tenant}.us8.webtask.io/auth0-delegated-admin` |
+ | Europe | `https://${account.tenant}.eu8.webtask.io/auth0-delegated-admin` |
+ | Australia | `https://${account.tenant}.au8.webtask.io/auth0-delegated-admin` |
+
+ If you are using Node 12:
+
+ | Location | Allowed Callback URL |
+ | --------- | -------------------- |
+ | USA | `https://${account.tenant}.us12.webtask.io/auth0-delegated-admin/login` |
+ | Europe | `https://${account.tenant}.eu12.webtask.io/auth0-delegated-admin/login` |
+ | Australia | `https://${account.tenant}.au12.webtask.io/auth0-delegated-admin/login` |
+
+ | Location | Allowed Logout URL |
+ | --------- | ------------------ |
+ | USA | `https://${account.tenant}.us12.webtask.io/auth0-delegated-admin` |
+ | Europe | `https://${account.tenant}.eu12.webtask.io/auth0-delegated-admin` |
+ | Australia | `https://${account.tenant}.au12.webtask.io/auth0-delegated-admin` |
+
+Next, you will need to [install the Delegated Admin Extension](/dashboard/guides/extensions/delegated-admin-install-extension).
+
+## Keep reading
+
+- [Troubleshoot Extensions](/extensions/troubleshoot)
diff --git a/articles/dashboard/guides/extensions/delegated-admin-install-extension.md b/articles/dashboard/guides/extensions/delegated-admin-install-extension.md
new file mode 100644
index 0000000000..18d081ae1e
--- /dev/null
+++ b/articles/dashboard/guides/extensions/delegated-admin-install-extension.md
@@ -0,0 +1,47 @@
+---
+description: Learn how to install the Delegated Administration Extension, which allows you to expose the Users section of the Auth0 Dashboard to a select group of users without allowing them access to the rest of the Dashboard.
+topics:
+ - extensions
+ - delegated-admin
+ - dae
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - setup-delegated-admin
+ - install-delegated-admin-extension
+---
+# Install the Delegated Admin Extension
+
+This guide will show you how to install the [Delegated Admin Extension](/extensions/delegated-admin), which allows you to expose the Users section of the Auth0 Dashboard to a select group of users without allowing them access to the rest of the Dashboard.
+
+::: warning
+Before you install and configure the Delegated Admin extension, you need to [create a Delegated Admin Dashboard application](/dashboard/guides/extensions/delegated-admin-create-app) in Auth0.
+:::
+
+1. Go to [Dashboard > Extensions](${manage_url}/#/extensions) and filter for `Delegated Admin`.
+
+2. Click on the **Delegated Administration Dashboard** box in the list of provided extensions. The **Install Extension** window will open.
+
+3. Set the following configuration variables:
+
+ | Variable | Description |
+ | --- | --- |
+ | **EXTENSION_CLIENT_ID** | **Client ID** of the application with which you plan to use this extension. |
+ | **TITLE** | Custom title that will appear at the top of the Delegated Administration Dashboard page. |
+ | **CUSTOM_CSS** | (*Optional*) Link to a custom CSS you can use to style the look of your Delegated Administration Dashboard page. |
+ | **FAVICON_PATH** | (*Optional*) Path to custom favicon. |
+ | **AUTH0_CUSTOM_DOMAIN** | (*Optional*) If you have a custom domain name configured, enter it here (e.g., `login.example.com`). This will change the authorization endpoint to `https://login.example.com/login`. |
+ | **FEDERATED_LOGOUT** | (*Optional*) Indicates whether to sign out from the connection when users log out. |
+
+::: note
+Setting the `AUTH0_CUSTOM_DOMAIN` variable does not affect the extension URL, it only changes the authorization endpoint. When a custom domain is used, users that are logging into the extension will be navigated to `https://AUTH0_CUSTOM_DOMAIN/login` instead of the default `https://tenant-name.us.auth0.com/login`.
+:::
+
+4. Click **Install**.
+
+ If you navigate back to the [Applications](${manage_url}/#/applications) view, you will see that there has been an additional application created by the extension. This application is authorized to access the [Management API](/api/management/v2), so you shouldn't modify it.
+
+ 
+
+Next, learn how to [use the Delegated Admin Extension](/dashboard/guides/extensions/delegated-admin-use-extension).
\ No newline at end of file
diff --git a/articles/dashboard/guides/extensions/delegated-admin-use-extension.md b/articles/dashboard/guides/extensions/delegated-admin-use-extension.md
new file mode 100644
index 0000000000..2947940e9b
--- /dev/null
+++ b/articles/dashboard/guides/extensions/delegated-admin-use-extension.md
@@ -0,0 +1,32 @@
+---
+description: Learn how to use the Delegated Administration Extension, which allows you to expose the Users section of the Auth0 Dashboard to a select group of users without allowing them access to the rest of the Dashboard.
+topics:
+ - extensions
+ - delegated-admin
+ - dae
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - setup-delegated-admin
+ - use-delegated-admin
+---
+# Use the Delegated Admin Extension
+
+This guide will show you how to use the [Delegated Admin Extension](/extensions/delegated-admin), which allows you to expose the Users section of the Auth0 Dashboard to a select group of users without allowing them access to the rest of the Dashboard.
+
+::: warning
+Before you can use the Delegated Admin extension, you need to [create a Delegated Admin Dashboard application](/dashboard/guides/extensions/delegated-admin-create-app) in Auth0 and [install the Delegated Admin extension](/dashboard/guides/extensions/delegated-admin-install-extension).
+:::
+
+1. Navigate to the [Extensions](${manage_url}/#/extensions) page and click on the **Installed Extensions** tab.
+
+2. Click on the row for the **Delegated Administration Dashboard** extension. A new tab will open to display the login prompt.
+
+ 
+
+ Because we disabled signups for the database connection while configuring it, the login screen will not display a Sign Up option.
+
+ Once you provide valid credentials, you will be directed to your custom **Delegated Administration Dashboard** page, which will have the **TITLE** you provided at the top of the page, and if you provided a custom CSS file, that styling will be applied.
+
+ 
diff --git a/articles/dashboard/guides/extensions/sso-dashboard-add-apps.md b/articles/dashboard/guides/extensions/sso-dashboard-add-apps.md
new file mode 100644
index 0000000000..a7ae60501c
--- /dev/null
+++ b/articles/dashboard/guides/extensions/sso-dashboard-add-apps.md
@@ -0,0 +1,70 @@
+---
+description: Learn how to add applications to the SSO Dashboard Extension to enable SSO login for your applications.
+topics:
+ - extensions
+ - sso-dashboard
+ - sso
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - setup-multiple-applications
+ - setup-sso-dashboard
+---
+
+# Add Applications to the SSO Dashboard
+
+Use the [SSO Dashboard Extension](/extensions/sso-dashboard) to manage SSO login for your users on multiple enterprise applications.
+
+Before you add the applications to the SSO Dashboard, you need to:
+
+* [Create the SSO Dashboard application](/dashboard/guides/extensions/sso-dashboard-create-app)
+* [Install the SSO Dashboard Extension](/dashboard/guides/extensions/sso-dashboard-install-extension)
+
+1. Go to [Dashboard > Extensions](${manage_url}/#/extensions) and click on your new SSO Dashboard extension.
+
+::: note
+If you are an administrator, you can also login to the SSO Dashboard using `https://${account.tenant}.8.webtask.io/auth0-sso-dashboard/admins/login`.
+:::
+
+2. In the upper right corner, select **Settings** from the dropdown below your tenant name.
+
+3. Click **CREATE APP** to add a new application.
+
+ 
+
+ The **New Application** form appears.
+
+ 
+
+4. Complete the following fields for the new application:
+
+ | Field | Description |
+ | --- | --- |
+ | **Type** | A dropdown where you select SAML, OpenID-Connect, or WS-Federation depending on the type of application. |
+ | **Application** | A dropdown where you select the application that you wish to add. |
+ | **Name** | The name is automatically populated based on the application you selected. You can change the name or use the default. |
+ | **Logo** | The url of the logo you wish to user as an icon for the application. |
+ | **Callback** | One of the **Allowed Callback URLs** under your [Application Settings](${manage_url}/#/applications) for the application. |
+ | **Connection** | (*Optional*) The connection type. You can add or edit your available connection types in the [Connections section of the Auth0 Management dashboard](${manage_url}/#/connections/database). If a connection is not set and the user is not logged, the user will see the Auth0 Login page. |
+ | **Custom URL** | (*Optional*) Checkbox to use a custom URL rather than the Auth0 URL. If you check the box, a field appears where you can enter your custom URL. |
+ | **Enabled** | Checkbox for this application to be visible (published) to your users. |
+
+5. Click **CREATE**.
+
+ Your new application will then appear on the **Applications** page of the SSO dashboard with any other applications that have been created.
+
+ 
+
+6. Click on an application to test the connection.
+
+## Keep reading
+
+- [Update Applications on the SSO Dashboard](/dashboard/guides/extensions/sso-dashboard-update-apps)
+- [View this Extension on GitHub](https://github.com/auth0-extensions/auth0-sso-dashboard-extension)
+- [Troubleshoot Extensions](/extensions/troubleshoot)
+- [Understand how Single Sign-On works with Auth0](/sso/current/sso-auth0)
+- Learn how to [enable SSO in Auth0](/dashboard/guides/tenants/enable-sso-tenant)
+- [Understand session lifetime](/sessions/concepts/session-lifetime)
+- Learn how to [configure session lifetime settings](/dashboard/guides/tenants/configure-session-lifetime-settings)
+- Learn how to [log users out](/logout)
diff --git a/articles/dashboard/guides/extensions/sso-dashboard-create-app.md b/articles/dashboard/guides/extensions/sso-dashboard-create-app.md
new file mode 100644
index 0000000000..32fe012956
--- /dev/null
+++ b/articles/dashboard/guides/extensions/sso-dashboard-create-app.md
@@ -0,0 +1,89 @@
+---
+description: Learn how to create an application to use with the SSO Dashboard Extension to enable SSO login for your applications.
+topics:
+ - extensions
+ - sso-dashboard
+ - sso
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - setup-multiple-sso-applications
+ - create-sso-dashboard-application
+---
+
+# Create a SSO Dashboard Application
+
+Use the [SSO Dashboard Extension](/extensions/sso-dashboard) to manage SSO login for your users on multiple enterprise applications.
+
+Before you [add the SSO Dashboard extension](/dashboard/guides/extensions/sso-dashboard-install-extension), you need to create the SSO Dashboard application in Auth0.
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click **+Create Application**.
+
+2. Enter a descriptive name for your Application (for example, *SSO Dashboard*), select an application type of **Single-Page Web Application**, and click **Create**.
+
+ 
+
+3. On the **Settings** tab, set the **Allowed Callback URLs** based on your location.
+
+ For **Admins**:
+
+ If you are using Node 8:
+
+ | Location | Allowed Callback URL |
+ | --- | --- |
+ | USA | `https://${account.tenant}.us8.webtask.io/auth0-sso-dashboard/admins/login` |
+ | Europe | `https://${account.tenant}.eu8.webtask.io/auth0-sso-dashboard/admins/login` |
+ | Australia | `https://${account.tenant}.au8.webtask.io/auth0-sso-dashboard/admins/login` |
+
+ If you are using Node 12:
+
+ | Location | Allowed Callback URL |
+ | --- | --- |
+ | USA | `https://${account.tenant}.us12.webtask.io/auth0-sso-dashboard/admins/login` |
+ | Europe | `https://${account.tenant}.eu12.webtask.io/auth0-sso-dashboard/admins/login` |
+ | Australia | `https://${account.tenant}.au12.webtask.io/auth0-sso-dashboard/admins/login` |
+
+ For **Users**:
+
+ If you are using Node 8:
+
+ | Location | Allowed Callback URL |
+ | --- | --- |
+ | USA | `https://${account.tenant}.us8.webtask.io/auth0-sso-dashboard/login` |
+ | Europe | `https://${account.tenant}.eu8.webtask.io/auth0-sso-dashboard/login` |
+ | Australia | `https://${account.tenant}.au8.webtask.io/auth0-sso-dashboard/login` |
+
+ If you are using Node 12:
+
+ | Location | Allowed Callback URL |
+ | --- | --- |
+ | USA | `https://${account.tenant}.us12.webtask.io/auth0-sso-dashboard/login` |
+ | Europe | `https://${account.tenant}.eu12.webtask.io/auth0-sso-dashboard/login` |
+ | Australia | `https://${account.tenant}.au12.webtask.io/auth0-sso-dashboard/login` |
+
+4. Select and copy the **Client ID** value.
+
+5. Scroll to the bottom of the page, and click **Show Advanced Settings**.
+
+6. Click the **OAuth** tab, and paste the **Client ID** value into the **Allowed APPs / APIs** field.
+
+7. Make sure that the **JsonWebToken Signature Algorithm** is set to **RS256**.
+
+8. Click **Save Changes**.
+
+ Next, you will need to [install the SSO Dashboard Extension](/dashboard/guides/extensions/sso-dashboard-install-extension) and [add applications](/dashboard/guides/extensions/sso-dashboard-add-apps) to the dashboard.
+
+::: note
+By default all the connection types are enabled for users to be able to login into the SSO Dashboard. If you would like to change this, navigate to the **Connections** tab for the Application.
+:::
+
+## Keep reading
+
+- [View this Extension on GitHub](https://github.com/auth0-extensions/auth0-sso-dashboard-extension)
+- [Troubleshoot Extensions](/extensions/troubleshoot)
+- [Understand how Single Sign-On works with Auth0](/sso/current/sso-auth0)
+- [Enable SSO in Auth0](/dashboard/guides/tenants/enable-sso-tenant)
+- [Understand Session Lifetime](/sessions/concepts/session-lifetime)
+- [Configure Session Lifetime Settings](/dashboard/guides/tenants/configure-session-lifetime-settings)
+- [Log Users Out](/logout)
diff --git a/articles/dashboard/guides/extensions/sso-dashboard-install-extension.md b/articles/dashboard/guides/extensions/sso-dashboard-install-extension.md
new file mode 100644
index 0000000000..63334cdce9
--- /dev/null
+++ b/articles/dashboard/guides/extensions/sso-dashboard-install-extension.md
@@ -0,0 +1,80 @@
+---
+description: Learn how to install the SSO Dashboard Extension to enable SSO login for your applications.
+topics:
+ - extensions
+ - sso-dashboard
+ - sso
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - setup-multiple-applications
+ - setup-sso-dashboard
+ - install-sso-dashboard-extension
+---
+
+# Install the SSO Dashboard Extension
+
+Use the [SSO Dashboard Extension](/extensions/sso-dashboard) to manage SSO login for your users on multiple enterprise applications.
+
+Before you install and configure the SSO Dashboard extension, you need to [create a SSO Dashboard application](/dashboard/guides/extensions/sso-dashboard-create-app) in Auth0.
+
+::: note
+Make sure you have copied the **Client ID** value from your SSO Dashboard application.
+:::
+
+1. Go to [Dashboard > Extensions](${manage_url}/#/extensions) and click on your new SSO Dashboard extension.
+
+2. Click on the **SSO Dashboard** box in the list of provided extensions. The **Install Extension** window will open.
+
+ 
+
+3. Set the following configuration variables:
+
+ | Variable | Description |
+ | --- | --- |
+ | **EXTENSION_CLIENT_ID** | The **Client ID** of the application you have created in the [Applications](${manage_url}/#/applications) that you wish to use this extension with. |
+ | **TITLE** | The custom title that will appear at the top of the SSO Dashboard page. |
+ | **CUSTOM_CSS** | (*Optional*) A link to a custom CSS you can use to style the look of your SSO Dashboard page. |
+ | **FAVICON_PATH** | (*Optional*) Path to custom favicon. |
+ | **AUTH0_CUSTOM_DOMAIN** | (*Optional*) If you have a custom domain name configured, enter it here (for example: `login.example.com`). This will change the authorization endpoint to `https://login.example.com/login`. |
+
+::: note
+Setting the `AUTH0_CUSTOM_DOMAIN` variable does not affect the extension URL, it only changes the authorization endpoint. When a custom domain is used, users that are logging into the extension will be navigated to `https://AUTH0_CUSTOM_DOMAIN/login` instead of the default `https://tenant-name.us.auth0.com/login`.
+:::
+
+4. Click **INSTALL**.
+
+ If you navigate back to the [Applications](${manage_url}/#/applications) view, you will see that there has been an additional application created.
+
+ 
+
+::: note
+The `auth0-sso-dashboard` application is created automatically when you install the extension. It's an application authorized to access the [Management API](/api/management/v2) and you shouldn't modify it.
+:::
+
+5. To use the extension, navigate to the [Extensions](${manage_url}/#/extensions) page and click on the **Installed Extensions** tab.
+
+6. Click on the row for the **SSO Dashboard** extension. The first time you click on your installed extension, you will be asked to grant it the required permissions.
+
+ Once you agree, you will be directed to your custom **SSO Dashboard** page, which will have the **TITLE** you provided at the top of the page, and if you provided a custom CSS file that styling will be applied.
+
+ 
+
+7. To login into the dashboard:
+
+ For **Admins** use `https://${account.tenant}.8.webtask.io/auth0-sso-dashboard/admins/login` or through the Dashboard.
+
+ For **Users** use `https://${account.tenant}.8.webtask.io/auth0-sso-dashboard/login`.
+
+## Keep reading
+
+- [Add Applications to the SSO Dashboard](/dashboard/guides/extensions/sso-dashboard-add-apps)
+- [Update Applications on the SSO Dashboard](/dashboard/guides/extensions/sso-dashboard-update-apps)
+- [View this Extension on GitHub](https://github.com/auth0-extensions/auth0-sso-dashboard-extension)
+- [Troubleshoot Extensions](/extensions/troubleshoot)
+- [Understand how Single Sign-On works with Auth0](/sso/current/sso-auth0)
+- Learn how to [enable SSO in Auth0](/dashboard/guides/tenants/enable-sso-tenant)
+- [Understand session lifetime](/sessions/concepts/session-lifetime)
+- Learn how to [configure session lifetime settings](/dashboard/guides/tenants/configure-session-lifetime-settings)
+- Learn how to [log users out](/logout)
diff --git a/articles/dashboard/guides/extensions/sso-dashboard-update-apps.md b/articles/dashboard/guides/extensions/sso-dashboard-update-apps.md
new file mode 100644
index 0000000000..5bced365a9
--- /dev/null
+++ b/articles/dashboard/guides/extensions/sso-dashboard-update-apps.md
@@ -0,0 +1,49 @@
+---
+description: Learn how to update applications on the SSO Dashboard Extension to enable SSO login for your applications.
+topics:
+ - extensions
+ - sso-dashboard
+ - sso
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - setup-multiple-applications
+ - update-sso-dashboard-applications
+---
+
+# Update Applications on the SSO Dashboard
+
+Use the [SSO Dashboard Extension](/extensions/sso-dashboard) to manage SSO login for your users on multiple enterprise applications.
+
+Before you can update the applications to the SSO Dashboard, you need to
+
+* [Create the SSO Dashboard application](/dashboard/guides/extensions/sso-dashboard-create-app) in Auth0
+* [Install the SSO Dashboard Extension](/dashboard/guides/extensions/sso-dashboard-install-extension)
+* [Add applications to the SSO Dashboard](/dashboard/guides/extensions/sso-dashboard-add-apps)
+
+1. Go to [Dashboard > Extensions](${manage_url}/#/extensions) and click on your new SSO Dashboard extension.
+
+::: note
+If you are an administrator, you can also login to the SSO Dashboard using `https://${account.tenant}.8.webtask.io/auth0-sso-dashboard/admins/login`.
+:::
+
+2. In the upper right corner, select **Settings** from the dropdown below your tenant name.
+
+3. Click **Publish** or **Unpublish** to change whether users can see the application (if it is enabled).
+
+4. Click the gear icon to update an application's settings.
+
+ 
+
+5. Delete an application with the **X** button. A confirmation box will popup to confirm the deletion.
+
+## Keep reading
+
+- [View this Extension on GitHub](https://github.com/auth0-extensions/auth0-sso-dashboard-extension)
+- [Troubleshoot Extensions](/extensions/troubleshoot)
+- [Understand how Single Sign-On works with Auth0](/sso/current/sso-auth0)
+- Learn how to [enable SSO in Auth0](/dashboard/guides/tenants/enable-sso-tenant)
+- [Understand session lifetime](/sessions/concepts/session-lifetime)
+- Learn how to [configure session lifetime settings](/dashboard/guides/tenants/configure-session-lifetime-settings)
+- Learn how to [log users out](/logout)
diff --git a/articles/dashboard/guides/roles/add-permissions-roles.md b/articles/dashboard/guides/roles/add-permissions-roles.md
new file mode 100644
index 0000000000..b475db3a84
--- /dev/null
+++ b/articles/dashboard/guides/roles/add-permissions-roles.md
@@ -0,0 +1,35 @@
+---
+title: Add Permissions to Roles
+description: Learn how to add permissions to roles for Auth0's API Authorization Core feature using the Auth0 Management Dashboard.
+topics:
+ - authorization
+ - dashboard
+ - roles
+ - permissions
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Add Permissions to Roles
+
+This guide will show you how to add permissions to [roles](/authorization/concepts/rbac) using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/add-permissions-roles). The roles and their permissions can be used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+<%= include('../../../authorization/_includes/_predefine-roles') %>
+<%= include('../../../authorization/_includes/_predefine-permissions') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the role to view.
+
+
+
+2. Click the **Permissions** tab, then click **Add Permissions**.
+
+
+
+3. Select the API from which you want to assign permissions, then select the permissions to add to the role, and click **Add Permissions**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/roles/create-roles.md b/articles/dashboard/guides/roles/create-roles.md
new file mode 100644
index 0000000000..fd7d58683f
--- /dev/null
+++ b/articles/dashboard/guides/roles/create-roles.md
@@ -0,0 +1,37 @@
+---
+title: Create Roles
+description: Learn how to create a role using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Create Roles
+
+This guide will show you how to create [roles](/authorization/concepts/rbac) using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/create-roles). The roles can be used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+<%= include('../../../authorization/_includes/_predefine-permissions') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click **Create Role**.
+
+
+
+2. Name the role and add a description, then click **Create**.
+
+
+
+3. Click **Add Permissions**.
+
+
+
+4. Select the API from which you want to add permissions, then select the permissions to add to the role, and click **Add Permissions**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/roles/delete-roles.md b/articles/dashboard/guides/roles/delete-roles.md
new file mode 100644
index 0000000000..26a4221716
--- /dev/null
+++ b/articles/dashboard/guides/roles/delete-roles.md
@@ -0,0 +1,28 @@
+---
+title: Delete Roles
+description: Learn how to delete a role using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Delete Roles
+
+This guide will show you how to delete a [role](/authorization/concepts/rbac) using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/delete-roles). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the Role to view.
+
+
+
+2. Click **Remove this Role**, and confirm.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/roles/edit-role-definitions.md b/articles/dashboard/guides/roles/edit-role-definitions.md
new file mode 100644
index 0000000000..64a5b4ebad
--- /dev/null
+++ b/articles/dashboard/guides/roles/edit-role-definitions.md
@@ -0,0 +1,28 @@
+---
+title: Edit Role Definitions
+description: Learn how to edit a role definition using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Edit Role Definitions
+
+This guide will show you how to edit a [role](/authorization/concepts/rbac) definition using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/edit-role-definitions). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the role to view.
+
+
+
+2. Edit the role name and description, then click **Update Role**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/roles/remove-role-permissions.md b/articles/dashboard/guides/roles/remove-role-permissions.md
new file mode 100644
index 0000000000..87caa7464c
--- /dev/null
+++ b/articles/dashboard/guides/roles/remove-role-permissions.md
@@ -0,0 +1,28 @@
+---
+title: Remove Permissions from Roles
+description: Learn how to remove permissions added to a role using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Remove Permissions from Roles
+
+This guide will show you how to remove the [permissions](/authorization/concepts/rbac) assigned to a role using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/remove-role-permissions). The assigned permissions and roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the role to view.
+
+
+
+2. Click the **Permissions** view, then click the trashcan icon next to the permission you want to remove, and confirm.
+
+
diff --git a/articles/dashboard/guides/roles/remove-role-users.md b/articles/dashboard/guides/roles/remove-role-users.md
new file mode 100644
index 0000000000..54197358ec
--- /dev/null
+++ b/articles/dashboard/guides/roles/remove-role-users.md
@@ -0,0 +1,29 @@
+---
+title: Remove Users from Roles
+description: Learn how to remove users assigned to a role using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+ - users
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Remove Users from Roles
+
+This guide will show you how to remove the users assigned to a [role](/authorization/concepts/rbac) using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/remove-role-users). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the role to view.
+
+
+
+2. Click the **Users** tab, then click the trashcan icon next to the user you want to remove, and confirm.
+
+
diff --git a/articles/dashboard/guides/roles/view-role-permissions.md b/articles/dashboard/guides/roles/view-role-permissions.md
new file mode 100644
index 0000000000..6edaba94e5
--- /dev/null
+++ b/articles/dashboard/guides/roles/view-role-permissions.md
@@ -0,0 +1,36 @@
+---
+title: View Role Permissions
+description: Learn how to view permissions added to a role using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View Role Permissions
+
+This guide will show you how to view the [permissions](/authorization/concepts/rbac) added to a role using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/view-role-permissions). The assigned permissions and roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the role to view.
+
+
+
+2. Click the **Permissions** view.
+
+
+
+The following information is displayed for each permission:
+
+| **Column** | **Description** |
+|----------------|-----------------|
+| Name | Name of the permission from the permission definition. |
+| Description | Description of the permission from the permission definition. |
+| API | Name of the API to which the permission is attached. |
\ No newline at end of file
diff --git a/articles/dashboard/guides/roles/view-role-users.md b/articles/dashboard/guides/roles/view-role-users.md
new file mode 100644
index 0000000000..6cf40ff358
--- /dev/null
+++ b/articles/dashboard/guides/roles/view-role-users.md
@@ -0,0 +1,37 @@
+---
+title: View Role Users
+description: Learn how to view users assigned to a role using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+ - users
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View Role Users
+
+This guide will show you how to view the users assigned to a [role](/authorization/concepts/rbac) using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/roles/view-role-users). Roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Roles](${manage_url}/#/roles) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the role to view.
+
+
+
+2. Click the **Users** view.
+
+
+
+The following information is displayed for each user:
+
+| **Attribute** | **Description** |
+|---------------|-----------------|
+| Picture | User's picture from the user profile. |
+| Name | User's name from the user profile. |
+| Email address | User's email address from the user profile. |
\ No newline at end of file
diff --git a/articles/dashboard/guides/rules/configure-variables.md b/articles/dashboard/guides/rules/configure-variables.md
new file mode 100644
index 0000000000..746106ce23
--- /dev/null
+++ b/articles/dashboard/guides/rules/configure-variables.md
@@ -0,0 +1,33 @@
+---
+title: Configure Global Variables for Rules
+description: Learn how to configure global variables for rules using the Auth0 Management Dashboard. Global variables are available to all rules via the configuration object.
+topics:
+ - rules
+ - variables
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Configure Global Variables for Rules
+
+This guide will show you how to configure global variables for [rules](/rules) using Auth0's Dashboard.
+
+1. Navigate to the [Rules](${manage_url}/#/rules) page in the [Auth0 Dashboard](${manage_url}/), and locate the **Settings** section.
+
+::: note
+To see the **Settings** section, you must have already created at least one rule.
+:::
+
+
+
+2. Enter a variable key/value pair, and click **Add**.
+
+
+
+The entered value is now available to all rules via the global `configuration` object and can be referenced using the value in the **Code Snippet** column.
+
+
diff --git a/articles/dashboard/guides/rules/create-rules.md b/articles/dashboard/guides/rules/create-rules.md
new file mode 100644
index 0000000000..053087ca0f
--- /dev/null
+++ b/articles/dashboard/guides/rules/create-rules.md
@@ -0,0 +1,33 @@
+---
+title: Create Rules
+description: Learn how to create a rule using the Auth0 Management Dashboard. You can use rules to customize and extend Auth0's capabilities.
+topics:
+ - dashboard
+ - rules
+ - extensibility
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Create Rules
+
+This guide will show you how to create [rules](/rules) using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/rules/create-rules).
+
+::: warning
+If you plan to use global variables in your rule, be sure to [configure your rules variables](/dashboard/guides/rules/configure-variables) first.
+:::
+
+1. Navigate to the [Rules](${manage_url}/#/rules) page in the [Auth0 Dashboard](${manage_url}/), and click **Create Rule**.
+
+
+
+2. Select a rule template.
+
+
+
+3. Name the rule, modify the script to suit your needs, and click **Save Changes**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/tenants/configure-device-user-code-settings.md b/articles/dashboard/guides/tenants/configure-device-user-code-settings.md
new file mode 100644
index 0000000000..94d7ca387d
--- /dev/null
+++ b/articles/dashboard/guides/tenants/configure-device-user-code-settings.md
@@ -0,0 +1,34 @@
+---
+title: Configure Device User Code Settings
+description: Learn how to configure the user code generated by your applications during the device authorization flow using the Auth0 Management Dashboard.
+topics:
+ - device-auth
+ - api-authentication
+ - device-flow
+ - native-apps
+ - desktop-apps
+ - mobile-apps
+ - devices
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - secure-api
+ - call-api
+---
+# Configure Device User Code Settings
+
+This guide will show you how to configure settings for the user code generated by your applications during the [Device Authorization Flow](/flows/concepts/device-auth) using Auth0's Dashboard.
+
+1. Navigate to the [Tenant Settings](${manage_url}/#/tenant) page in the [Auth0 Dashboard](${manage_url}/), and click the [**Advanced**](${manage_url}/#/tenant/advanced) tab.
+
+
+
+2. Scroll to the **Device Flow User Code Format** section, locate **User Code Character Set** and **User Code Mask**, enter the desired settings, and click **Save**.
+
+
+
+| Setting | Description |
+| ------- | ----------- |
+| **Device Flow User Code Format** | Character set used to when randomly generating a user code. |
+| **User Code Mask** | Mask used to define length and format of a randomly-generated user code. Its purpose is to increase the user code's readability and ease of input. |
diff --git a/articles/dashboard/guides/tenants/configure-session-lifetime-settings.md b/articles/dashboard/guides/tenants/configure-session-lifetime-settings.md
new file mode 100644
index 0000000000..68438a77f0
--- /dev/null
+++ b/articles/dashboard/guides/tenants/configure-session-lifetime-settings.md
@@ -0,0 +1,31 @@
+---
+title: Configure Session Lifetime Settings
+description: Learn how to configure session lengths and limits for a tenant using the Auth0 Management Dashboard.
+topics:
+ - idle-timeout
+ - absolute-timeout
+ - session-lifetime-limits
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - integrate-saas-sso
+ - configure-sso
+ - build-an-app
+---
+# Configure Session Lifetime Settings
+
+This guide will show you how to configure session settings for your tenant using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/tenants/configure-session-lifetime-settings).
+
+1. Navigate to the [Tenant Settings](${manage_url}/#/tenant) page in the [Auth0 Dashboard](${manage_url}/), and click the [**Advanced**](${manage_url}/#/tenant/advanced) tab.
+
+
+
+2. Scroll to the **Log In Session Management** section, locate **Inactivity timeout** and **Require log in after**, enter the desired settings, and click **Save**.
+
+
+
+| Setting | Description |
+| ------- | ----------- |
+| **Inactivity timeout** | Timeframe (in minutes) after which a user's session will expire if they haven’t interacted with the Authorization Server. Will be superseded by system limits if over 4,320 minutes (3 days) for Developer or Developer Pro or 144,000 minutes (100 days) for enterprise plans. |
+| **Require log in after** | Timeframe (in minutes) after which a user will be required to log in again, regardless of their activity. Will be superseded by system limits if over 43,200 minutes (30 days) for Developer or Developer Pro or 525,600 minutes (365 days) for enterprise plans. |
\ No newline at end of file
diff --git a/articles/dashboard/guides/tenants/create-multiple-tenants.md b/articles/dashboard/guides/tenants/create-multiple-tenants.md
new file mode 100644
index 0000000000..89732892af
--- /dev/null
+++ b/articles/dashboard/guides/tenants/create-multiple-tenants.md
@@ -0,0 +1,28 @@
+---
+description: Learn how to create an additional tenant using the Auth0 Management Dashboard.
+topics:
+ - dashboard
+ - tenants
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# Create Multiple Tenants
+
+You can configure multiple [tenants](/getting-started/the-basics#account-and-tenants) in the Auth0 Dashboard to allow for more complex configurations.
+
+For instance, if you have two separate domains (for example, one internal and one public-facing) or would like to allow users to log in differently for different applications, the best solution is to create more than one Auth0 tenant. This will allow you to have separate sets of applications, connections, and users for the applications and groups of users you need to support.
+
+1. Open the [Auth0 Dashboard](${manage_url}/), click your tenant name, and select **+ Create Tenant**.
+
+
+
+2. Enter your desired domain name, select a region, and click **Create**.
+
+
+
+## Keep reading
+
+* [Using Auth0 to Secure Your Multi-Tenant Applications](/design/using-auth0-with-multi-tenant-apps)
+* [Delete or Reset Tenants](/support/delete-reset-tenant)
diff --git a/articles/dashboard/guides/tenants/enable-sso-tenant.md b/articles/dashboard/guides/tenants/enable-sso-tenant.md
new file mode 100644
index 0000000000..6443be4bcd
--- /dev/null
+++ b/articles/dashboard/guides/tenants/enable-sso-tenant.md
@@ -0,0 +1,37 @@
+---
+title: Enable Single Sign-On
+description: Learn how to enable Single Sign-on (SSO) for a tenant using the Auth0 Management Dashboard. Only for use with legacy tenants.
+toc: true
+topics:
+ - sso
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - integrate-saas-sso
+ - configure-sso
+ - build-an-app
+---
+# Enable Single Sign-On
+
+By default, seamless Single Sign-on (SSO) is enabled for all new Auth0 tenants; however, legacy tenants may choose whether to enable this feature.
+
+This guide will show you how to enable Single Sign-on (SSO) for your tenant using Auth0's Dashboard.
+
+::: note
+If you do not choose to enable tenant-level SSO, you may [enable it per application](/dashboard/guides/applications/enable-sso-app).
+:::
+
+1. Navigate to the [Tenant Settings](${manage_url}/#/tenant) page in the [Auth0 Dashboard](${manage_url}/), and click the [**Advanced**](${manage_url}/#/tenant/advanced) tab.
+
+
+
+2. Scroll to the **Log In Session Management** section, locate **Enable Seamless SSO**, and enable the toggle.
+
+
+
+::: warning
+If you do not see this setting available in the Dashboard, you already have Seamless SSO enabled; this toggle is strictly for legacy tenants.
+:::
+
+Once finished, you should also [configure your session lifetime settings](/dashboard/guides/tenants/configure-session-lifetime-settings).
diff --git a/articles/dashboard/guides/tenants/revoke-signing-keys.md b/articles/dashboard/guides/tenants/revoke-signing-keys.md
new file mode 100644
index 0000000000..e1f64dda5d
--- /dev/null
+++ b/articles/dashboard/guides/tenants/revoke-signing-keys.md
@@ -0,0 +1,95 @@
+---
+title: Revoke Signing Keys
+description: Learn how to revoke your tenant's application signing key using the Auth0 Dashboard and Auth0 Management API. Application signing keys are used to sign ID Tokens, Access Tokens, SAML assertions, and WS-Fed assertions that are sent to your application.
+topics:
+ - tokens
+ - access-tokens
+ - id-tokens
+ - assertions
+ - SAML
+ - signing-keys
+ - certificates
+ - dashboard
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - secure-api
+ - add-login
+ - call-api
+---
+
+# Revoke Signing Keys
+
+You can revoke your tenant's application signing key using the Auth0 Dashboard and Auth0 Management API. The application signing key is used to sign ID Tokens, Access Tokens, SAML assertions, and WS-Fed assertions sent to your application. To learn more, see [Manage Signing Keys](/tokens/guides/manage-signing-keys).
+
+::: warning
+Before you can revoke a previously-used application signing key, you must first have rotated the key. To learn how, see [Rotate Signing Keys](/dashboard/guides/tenants/rotate-signing-keys), or learn how to [rotate and revoke signing keys at the same time](/dashboard/guides/tenants/revoke-signing-keys#rotate-and-revoke-signing-key).
+
+Make sure you have updated your application with the new key before you revoke the previous key.
+:::
+
+
+
+## Revoke signing key
+
+1. Navigate to the [Tenant Settings](${manage_url}/#/tenant) page in the [Auth0 Dashboard](${manage_url}/), and click the [**Signing Keys**](${manage_url}/#/tenant/signing_keys) tab.
+
+
+
+2. Scroll to the **List of Valid Keys** section, locate the **Previously Used** key, click its more options (**...**) menu, and select **Revoke Key**.
+
+
+
+3. Confirm revocation by clicking **Revoke**.
+
+
+
+## Rotate and revoke signing key
+
+1. Navigate to the [Tenant Settings](${manage_url}/#/tenant) page in the [Auth0 Dashboard](${manage_url}/), and click the [**Signing Keys**](${manage_url}/#/tenant/signing_keys) tab.
+
+
+
+2. In the **Rotation Settings** section, locate the **Rotate & Revoke Signing Key** section, and select **Rotate & Revoke Key**.
+
+
+
+3. Confirm rotation and revocation by clicking **Rotate & Revoke**.
+
+
+
+
+
+::: warning
+You may only revoke the previously used signing key.
+:::
+
+1. Make a `PUT` call to the [Revoke Signing Key endpoint](/api/management/v2#!/signing_keys/post_signing_key). Be sure to replace the `YOUR_KEY_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your signing key's ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "PUT",
+ "url": "https://${account.namespace}/api/v2/keys/signing/YOUR_KEY_ID/revoke",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `YOUR_KEY_ID` | ID of the signing key to be revoked. To learn how to find your signing key ID, see [Locate JSON Web Key Sets](/tokens/guides/locate-jwks). |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `update:signing_keys`. |
+
+
+
+
diff --git a/articles/dashboard/guides/tenants/rotate-signing-keys.md b/articles/dashboard/guides/tenants/rotate-signing-keys.md
new file mode 100644
index 0000000000..f2f29730c9
--- /dev/null
+++ b/articles/dashboard/guides/tenants/rotate-signing-keys.md
@@ -0,0 +1,76 @@
+---
+title: Rotate Signing Keys
+description: Learn how to rotate your tenant's application signing key using the Auth0 Dashboard and Auth0 Management API. Application signing keys are used to sign ID Tokens, Access Tokens, SAML assertions, and WS-Fed assertions that are sent to your application.
+topics:
+ - tokens
+ - access-tokens
+ - id-tokens
+ - assertions
+ - SAML
+ - signing-keys
+ - certificates
+ - dashboard
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - secure-api
+ - add-login
+ - call-api
+---
+
+# Rotate Signing Keys
+
+You can rotate your tenant's application signing key using the Auth0 Dashboard and Auth0 Management API. The application signing key is used to sign ID Tokens, Access Tokens, SAML assertions, and WS-Fed assertions sent to your application. To learn more, see [Manage Signing Keys](/tokens/guides/manage-signing-keys).
+
+::: warning
+To allow you time to update your application with the new key, all tokens signed with the previous key will still be valid until you revoke the previous key. To learn more, see [Revoke Signing Keys](/dashboard/guides/tenants/revoke-signing-keys), or learn how to [rotate and revoke signing keys at the same time](/dashboard/guides/tenants/revoke-signing-keys#rotate-and-revoke-signing-key).
+:::
+
+
+
+1. Navigate to the [Tenant Settings](${manage_url}/#/tenant) page in the [Auth0 Dashboard](${manage_url}/), and click the [**Signing Keys**](${manage_url}/#/tenant/signing_keys) tab.
+
+
+
+2. Scroll to the **Rotation Settings** section, locate **Rotate Signing Key**, and click **Rotate Key**.
+
+
+
+3. Confirm rotation by clicking **Rotate**.
+
+
+
+
+
+1. Make a `POST` call to the [Rotate Signing Keys endpoint](/api/management/v2#!/signing_keys/post_signing_key). Be sure to replace the `MGMT_API_ACCESS_TOKEN` placeholder value with your Management API Access Token.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/keys/signing/rotate",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scopes `create:signing_keys` and `update:signing_keys`. |
+
+
+
+
+
+
+
+
diff --git a/articles/dashboard/guides/tenants/view-signing-keys.md b/articles/dashboard/guides/tenants/view-signing-keys.md
new file mode 100644
index 0000000000..81e5575528
--- /dev/null
+++ b/articles/dashboard/guides/tenants/view-signing-keys.md
@@ -0,0 +1,99 @@
+---
+title: View Signing Keys
+description: Learn how to view your tenant's application signing keys using the Auth0 Dashboard and Auth0 Management API. Application signing keys are used to sign ID Tokens, Access Tokens, SAML assertions, and WS-Fed assertions that are sent to your application.
+topics:
+ - tokens
+ - access-tokens
+ - id-tokens
+ - assertions
+ - SAML
+ - signing-keys
+ - certificates
+ - dashboard
+ - mgmt-api
+contentType:
+ - how-to
+useCase:
+ - secure-api
+ - add-login
+ - call-api
+---
+
+# View Signing Keys
+
+You can view your tenant's application signing keys using the Auth0 Dashboard and Auth0 Management API. The application signing key is used to sign ID Tokens, Access Tokens, SAML assertions, and WS-Fed assertions sent to your application. To learn more, see [Manage Signing Keys](/tokens/guides/manage-signing-keys).
+
+::: note
+Note that these keys are different from those used to sign interactions with connections, including signing SAML Requests to IdPs and encrypting responses from IdPs.
+
+By default, SAML assertions for IdP connections are signed, which we recommend. To learn more, see [SAML Identity Provider Configuration: Signed Assertions](/protocols/saml/samlp#signed-assertions).
+:::
+
+
+
+1. Navigate to the [Tenant Settings](${manage_url}/#/tenant) page in the [Auth0 Dashboard](${manage_url}/), and click the [**Signing Keys**](${manage_url}/#/tenant/signing_keys) tab.
+
+
+
+2. Scroll to the **Settings** section, and locate **List of Valid Keys** and **List of Revoked Keys**.
+
+
+
+The **List of Valid Keys** section lists the current signing key being used by your tenant, plus the next signing key that will be assigned should you choose to rotate your signing keys. If you have previously rotated signing keys, this section also lists the previously used keys.
+
+The **List of Revoked Keys** section lists the last three revoked keys for your tenant.
+
+
+
+## Get all signing keys
+
+1. Make a `GET` call to the [Get All Signing Keys endpoint](/api/management/v2#!/signing_keys/get_signing_keys). Be sure to replace the `MGMT_API_ACCESS_TOKEN` placeholder value with your Management API Access Token.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/keys/signing",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `read:signing_keys`. |
+
+## Get a single signing key
+
+1. Make a `GET` call to the [Get a Signing Key endpoint](/api/management/v2#!/signing_keys/get_signing_key). Be sure to replace the `YOUR_KEY_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your signing key's ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/keys/signing/YOUR_KEY_ID",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `YOUR_KEY_ID` | ID of the signing key to be viewed. To learn how to find your signing key ID, see [Locate JSON Web Key Sets](/tokens/guides/locate-jwks). |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `read:signing_keys`. |
+
+
+
+
+
+
+
+
diff --git a/articles/dashboard/guides/universal-login/configure-login-page-passwordless.md b/articles/dashboard/guides/universal-login/configure-login-page-passwordless.md
new file mode 100644
index 0000000000..d522958afc
--- /dev/null
+++ b/articles/dashboard/guides/universal-login/configure-login-page-passwordless.md
@@ -0,0 +1,73 @@
+---
+title: Configure Universal Login with Passwordless
+description: Learn how to configure your login page for use with passwordless authentication using the Auth0 Management Dashboard.
+topics:
+ - universal-login
+ - passwordless
+ - login-page
+ - lock
+ - dashboard
+ - auth0-js
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+---
+# Configure Universal Login with Passwordless
+
+[Universal Login](/universal-login) is Auth0's implementation of the login flow, which is the key feature of an Authorization Server. Each time a user needs to prove their identity, your applications redirect to Universal Login and Auth0 will do what is needed to guarantee the user's identity. By choosing Universal Login, you don't have to do any integration work to handle the various flavors of authentication.
+
+This guide will show you how to set up a login page for use with [passwordless authentication](/connections/passwordless) using Auth0's Dashboard.
+
+::: warning
+For passwordless authentication to work properly when previewing your login page, you must first have [configured a passwordless connection](/connections/passwordless#implement-passwordless) for your application.
+:::
+
+When setting up a login page for passwordless, you have a few options. To learn how to configure your universal login page to use passwordless, select your implementation:
+
+
+
+## Universal Login + Lock (passwordless)
+
+This login page uses the [Classic](/universal-login/classic) [Universal Login](/universal-login) experience with the **Lock (passwordless)** template. To authenticate users, this template uses the [Auth0 Lock widget with Passwordless mode](/libraries/lock/v11#passwordless) and can be customized accordingly.
+
+1. Navigate to the [Universal Login](${manage_url}/#/login_settings) page in the [Auth0 Dashboard](${manage_url}/), and click the **Login** tab.
+
+2. Enable the **Custom Login Page** toggle, and select the **Lock (passwordless)** template.
+
+The HTML template will update with code using the Lock widget with passwordless customization options.
+
+3. Customize the template, and click **Save Changes**.
+
+You can use HTML and CSS to customize the login form. To learn more about how to customize the **Lock (passwordless)** template, see [Lock: Passwordless](/libraries/lock/v11#passwordless).
+
+You can preview customization changes. Make sure to select the correct application for which you want to preview the login page.
+
+
+
+## Universal Login + Custom UI + Auth0.js
+
+This login page uses the [Classic](/universal-login/classic) [Universal Login](/universal-login) experience with the **Custom Login Form** template. To authenticate users, this template uses the [Auth0.js SDK](/libraries/auth0js) and can be customized accordingly.
+
+1. Navigate to the [Universal Login](${manage_url}/#/login_settings) page in the [Auth0 Dashboard](${manage_url}/), and click the **Login** tab.
+
+2. Enable the **Custom Login Page** toggle, and select the **Custom Login Form** template.
+
+The HTML template will update with code using CSS and the Auth0.js SDK.
+
+3. Customize the template, and click **Save Changes**.
+
+You can use HTML and CSS to customize the login form. To learn more about how to use the Auth0.js SDK with the **Custom Login Form** template, see [Auth0.js SDK: Passwordless Login](/libraries/auth0js/v9#passwordless-login).
+
+You can preview customization changes. Make sure to select the correct application for which you want to preview the login page.
+
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/users/assign-permissions-users.md b/articles/dashboard/guides/users/assign-permissions-users.md
new file mode 100644
index 0000000000..895504e56f
--- /dev/null
+++ b/articles/dashboard/guides/users/assign-permissions-users.md
@@ -0,0 +1,53 @@
+---
+title: Assign Permissions to Users
+description: Learn how to assign permissions to a user using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Assign Permissions to Users
+
+This guide will show you how to assign [permissions](/authorization/concepts/rbac) to a user using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/users/assign-permissions-users). The assigned permissions can be used with the API Authorization Core feature set.
+
+::: note
+Adding permissions directly to a user circumvents the benefits of [role-based access control (RBAC)](/authorization/concepts/rbac) and is not typically recommended.
+:::
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+<%= include('../../../authorization/_includes/_predefine-permissions') %>
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/).
+
+
+
+2. Click **`...`** next to the user you want to modify, and select **Assign Permissions**.
+
+
+
+3. Select the API from which you want to assign permissions, then select the permissions to assign to the user, and click **Add Permissions**.
+
+
+
+You can also assign permissions to users from their individual profile page.
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the user to view.
+
+
+
+2. Click the **Permissions** tab, and click **Assign Permissions**.
+
+
+
+3. Select the API from which you want to assign permissions, then select the permissions to assign to the user, and click **Add Permissions**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/users/assign-roles-users.md b/articles/dashboard/guides/users/assign-roles-users.md
new file mode 100644
index 0000000000..273a365afc
--- /dev/null
+++ b/articles/dashboard/guides/users/assign-roles-users.md
@@ -0,0 +1,50 @@
+---
+title: Assign Roles to Users
+description: Learn how to assign roles to a user using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - roles
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Assign Roles to Users
+
+This guide will show you how to assign [roles](/authorization/concepts/rbac) to a user using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/users/assign-roles-users). The assigned roles can be used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+<%= include('../../../authorization/_includes/_predefine-roles') %>
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/).
+
+
+
+2. Click **`...`** next to the user you want to modify, and select **Assign Roles**.
+
+
+
+3. Choose the role(s) you wish to assign, then click **Assign**.
+
+
+
+
+You can also assign roles to users from their individual profile page.
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the user to view.
+
+
+
+2. Click the **Roles** view, and click **Assign Role**.
+
+
+
+3. Choose the role you wish to assign, then click **Assign**.
+
+
\ No newline at end of file
diff --git a/articles/dashboard/guides/users/create-users.md b/articles/dashboard/guides/users/create-users.md
new file mode 100644
index 0000000000..1ba0374261
--- /dev/null
+++ b/articles/dashboard/guides/users/create-users.md
@@ -0,0 +1,23 @@
+---
+title: Create Users
+description: Learn how to create a user using the Auth0 Management Dashboard.
+topics:
+ - dashboard
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Create Users
+
+This guide will show you how to create a user using Auth0's Dashboard.
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click **+ Create User**.
+
+
+
+2. Enter your user's **Email**, **Password**, and **Repeat Password**, then select the **Connection**, and click **Create**.
\ No newline at end of file
diff --git a/articles/dashboard/guides/users/remove-user-permissions.md b/articles/dashboard/guides/users/remove-user-permissions.md
new file mode 100644
index 0000000000..94353eef5c
--- /dev/null
+++ b/articles/dashboard/guides/users/remove-user-permissions.md
@@ -0,0 +1,29 @@
+---
+title: Remove Permissions from Users
+description: Learn how to remove permissions directly assigned to a user using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Remove Permissions from Users
+
+This guide will show you how to remove the [permissions](/authorization/concepts/rbac) directly assigned to a user using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/users/remove-user-permissions). The assigned permissions are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the user to view.
+
+
+
+2. Click the **Permissions** view, then click the trashcan icon next to the permission you want to remove, and confirm.
+
+
diff --git a/articles/dashboard/guides/users/remove-user-roles.md b/articles/dashboard/guides/users/remove-user-roles.md
new file mode 100644
index 0000000000..c231371b98
--- /dev/null
+++ b/articles/dashboard/guides/users/remove-user-roles.md
@@ -0,0 +1,30 @@
+---
+title: Remove Roles from Users
+description: Learn how to remove roles assigned to a user using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Remove Roles from Users
+
+This guide will show you how to remove the [roles](/authorization/concepts/rbac) assigned to a user using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/users/remove-user-roles). The assigned roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the user to view.
+
+
+
+2. Click the **Roles** view, then click the trashcan icon next to the role you want to remove.
+
+
diff --git a/articles/dashboard/guides/users/unlink-user-devices.md b/articles/dashboard/guides/users/unlink-user-devices.md
new file mode 100644
index 0000000000..d7c4a8f478
--- /dev/null
+++ b/articles/dashboard/guides/users/unlink-user-devices.md
@@ -0,0 +1,30 @@
+---
+title: Unlink Devices from Users
+description: Learn how to unlink devices assigned to a user using the Auth0 Management Dashboard. This effectively revokes the Refresh Token for the device.
+topics:
+ - authorization
+ - dashboard
+ - devices
+ - native-apps
+ - desktop-apps
+ - mobile-apps
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# Unlink Devices from Users
+
+This guide will show you how to unlink the devices assigned to a user using Auth0's Dashboard. This effectively revokes the Refresh Token for the selected device.
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the user to view.
+
+
+
+2. Click the **Devices** view, then click the trashcan icon next to the device you want to unlink, and confirm.
+
+
diff --git a/articles/dashboard/guides/users/view-user-permissions.md b/articles/dashboard/guides/users/view-user-permissions.md
new file mode 100644
index 0000000000..58e589c006
--- /dev/null
+++ b/articles/dashboard/guides/users/view-user-permissions.md
@@ -0,0 +1,38 @@
+---
+title: View User Permissions
+description: Learn how to view permissions assigned to a user using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View User Permissions
+
+This guide will show you how to view the [permissions](/authorization/concepts/rbac) assigned to a user using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/users/view-user-permissions). The assigned permissions are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the user to view.
+
+
+
+2. Click the **Permissions** view.
+
+
+
+The following information is displayed for each permission:
+
+| **Column** | **Description** |
+|------------|-----------------|
+| Name | Name of the permission from the permission definition. |
+| Description | Description of the permission from the permission definition. |
+| API | Name of the API to which the permission is attached. |
+| Assignment | Indicates whether the permission is directly assigned to the user or is assigned via a role. |
diff --git a/articles/dashboard/guides/users/view-user-roles.md b/articles/dashboard/guides/users/view-user-roles.md
new file mode 100644
index 0000000000..3e9f0d7ace
--- /dev/null
+++ b/articles/dashboard/guides/users/view-user-roles.md
@@ -0,0 +1,37 @@
+---
+title: View User Roles
+description: Learn how to view roles assigned to a user using the Auth0 Management Dashboard. For use with Auth0's API Authorization Core feature set.
+topics:
+ - authorization
+ - dashboard
+ - permissions
+ - roles
+ - users
+ - user-profile
+contentType:
+ - how-to
+useCase:
+ - build-an-app
+ - call-api
+ - secure-api
+---
+# View User Roles
+
+This guide will show you how to view the [roles](/authorization/concepts/rbac) assigned to a user using Auth0's Dashboard. This task can also be performed [using the Management API](/api/management/guides/users/view-user-roles). The assigned roles are used with the API Authorization Core feature set.
+
+<%= include('../../../authorization/_includes/_enable-authz-core') %>
+
+1. Navigate to the [Users & Roles > Users](${manage_url}/#/users) page in the [Auth0 Dashboard](${manage_url}/), and click the name of the user to view.
+
+
+
+2. Click the **Roles** view.
+
+
+
+The following information is displayed for each role:
+
+| **Column** | **Description** |
+|------------|-----------------|
+| Name | Name of the role from the role definition. |
+| Description | Description of the role from the role definition. |
diff --git a/articles/dashboard/index.md b/articles/dashboard/index.md
index 5d90582db9..a0742835c4 100644
--- a/articles/dashboard/index.md
+++ b/articles/dashboard/index.md
@@ -2,6 +2,12 @@
title: Dashboard
description: Working with the Dashboard
classes: topic-page
+topics:
+ - dashboard
+contentType:
+ - index
+ - how-to
+useCase: manage-accounts
---
+
diff --git a/articles/dashboard/manage-dashboard-admins.md b/articles/dashboard/manage-dashboard-admins.md
index 738897565f..9231bdb8f4 100644
--- a/articles/dashboard/manage-dashboard-admins.md
+++ b/articles/dashboard/manage-dashboard-admins.md
@@ -1,30 +1,88 @@
---
-description: How to add and remove tenant admins in the Auth0 dashboard.
+description: Learn how to manage tenant administrators in the Auth0 Dashboard.
+topics:
+ - dashboard
+ - admins
+contentType: how-to
+useCase:
+ - manage-users
+ - manage-accounts
---
-# Manage Admins in the Dashboard
+# Manage Tenant Administrators in the Dashboard
::: note
Please see [Reset Your Auth0 Account Password](/tutorials/reset-account-password) if you're having issues logging in.
:::
-Tenant Administrators can be added and removed from the dashboard, by going to **Tenant Settings** and choosing the [Dashboard Admins](${manage_url}/#/tenant/admins) tab.
+You can add, edit, and remove tenant administrators from the Dashboard by going to **Tenant Settings** > [Dashboard Admins](${manage_url}/#/tenant/admins).

-To add an Admin, enter the email of the account and then select the applications you would like this user to have admin access to in the **Application** box. Then click the **ADD** button. Admins can be removed by clicking the **REMOVE** button after they have been added.
+::: warning
+You are responsible for managing your tenant administrators, **including revoking privileges from users as necessary**. You are responsible for all activities that occur under your account/tenant.
+:::
-The MFA indicator will indicate whether an Admin has enabled their account for [Multifactor Authentication](/multifactor-authentication), which they can do in their Account Settings.
+## Add administrators
-
+To add an administrator, enter their email and select the applications to which you would like this user to have administrative access in the **Application** box. Click **ADD**.
+
+When the recipient opens and accepts the invitation, the current Auth0 account in the browser will be added as a Dashboard Admin (as long as the user is logged in with an account linked to the email address to which the invitation was sent; if not, the user will be prompted to log in with an account linked to the invitation email address). If there is no current session, the recipient will be prompted to log in or create an Auth0 account.
+
+::: note
+If the invited administrator has not created an Auth0 admin user account, they will need to do so in order to be able to accept the invitation and log into the Management Dashboard. Auth0 admin users are managed separately from tenant users; accounts can be created by following the invitation URL or signing up through [auth0.com/signup](https://auth0.com/signup).
+:::
+
+Administrators are application-specific, so areas to which the admin doesn't have access rights (e.g., APIs, Rules, Hooks, Universal Login Pages, and so on) will appear as blank pages. Administrators will also *not* be allowed to manage users, create rules, and perform other functions for applications to which they don't have access.
+
+::: panel Application-Specific Access
+Application-specific access includes the following:
+
+* Read and write access to the specific application configuration
+* Read access to enabled connections for the application
+* Ability to configure add-ons for the specific application
+* Read (not write) access to all user records
+
+In addition, a user can be invited to be an administrator for multiple applications, but each application invite must be sent and accepted individually.
+:::
+
+## Update administrators
+
+To update the email address associated with an existing tenant administrator, send an invite using the new email address. Once they accept the invite, you can remove the tenant administrator associated with the old email address.
-## Enrolling in Multifactor Authentication
+### Remove administrators
-The admin can self-enroll for multifactor authentication. To begin, they should click on their user name in the top right and going to **View Profile** in the dropdown menu.
+You can remove administrators by clicking **REMOVE** after they have been added.
+
+## Add, change or remove MFA
+
+The administrator can self-enroll for [Multi-factor Authentication](/mfa). The MFA indicator will indicate whether an administrator has enabled their account for MFA, which they can do in their Account Settings.
+
+### Add MFA
+
+
+
+To self-enroll for MFA, the administrator should click on their user name in the top right and going to **View Profile** in the dropdown menu.
Click **Enroll your device now.**

-Follow the on-screen instructions to complete your enrollment.
+Follow the on-screen instructions to complete the enrollment.
+
+### Remove or change MFA
+
+You can remove or change factors if they are lost.
+
+If you are changing devices and will no longer have your device, remove it by verifying MFA with that device. You will be prompted for it, and then it will be removed. If you no longer have access to your device, you can use your recovery code to do this process with the same results. Then, you can add a new device.
+
+If you no longer have access to your device or recovery code, another admin should file an Auth0 [support ticket](/support/tickets) on your behalf so Auth0 can verify the request and proceed with an MFA reset. This only applies for Dashboard Admin accounts. **Auth0 will not process end-user accounts MFA resets**, as we do not have control over our customer's tenants.
+
+## Add Support-Only Users
+
+If you want to allow employees of your organization to have access to our [Support Center](https://support.auth0.com), but you don't want to give them complete Administrator access over the tenant or a particular application, you can alternatively add them as Support-Only users. If that's the case, please follow the instructions described in our [Support Options](/support#add-support-only-users) documentation.
+
+## Find missing tenants
+We've occasionally found that Dashboard administrations inadvertently create multiple Auth0 accounts. For example, they might sign up with a social provider (e.g., Google, GitHub), then sign up again using the email address. If you have a Dashboard administrator that reports that they cannot see all of their tenants after logging in, check to see if they have multiple Auth0 accounts.
+You can confirm the signup method used by the Dashboard adminsitrator by going to **Tenant Settings** > [**Dashboard Admins**](${manage_url}/#/tenant/admins).
diff --git a/articles/dashboard/reference/settings-api.md b/articles/dashboard/reference/settings-api.md
new file mode 100644
index 0000000000..9173b77738
--- /dev/null
+++ b/articles/dashboard/reference/settings-api.md
@@ -0,0 +1,30 @@
+---
+title: API Settings
+description: Learn about the settings related to APIs available in the Auth0 Dashboard.
+topics:
+ - api-authentication
+ - oidc
+ - apis
+ - dashboard
+contentType: reference
+useCase:
+ - secure-api
+ - call-api
+---
+# API Settings
+
+On the [APIs](${manage_url}/#/apis) page of the [Auth0 Dashboard](${manage_url}/), locate your API and click its name to view the available settings.
+
+- **Id**: A unique alphanumeric string generated by Auth0. This information is read-only, and you will only need it if you will be working directly with [Auth0's Management API Resource Servers endpoints](/api/management/v2#!/Resource_Servers/get_resource_servers_by_id).
+
+- **Name**: A friendly name for the API. Does not affect any functionality. The following characters are not allowed: `< >`.
+
+- **Identifier**: A unique identifier for your API. This value is set upon API creation and cannot be modified afterwards. We recommend using a URL, but this doesn't have to be a publicly available URL; Auth0 will not call your API at all.
+
+- **Token Expiration (Seconds)**: The amount of time (in seconds) before the Auth0 Access Token expires. The default value is 86400 seconds (24 hours). The maximum value you can set is 2592000 seconds (30 days).
+
+- **Allow Skipping User Consent**: When this is enabled, the User Consent dialog will not be shown to the end user when a first-party application requests authorized access against your API. Please note that if the hostname of your application's **callbackURL** is `localhost` or `127.0.0.1`, the consent dialog will always be displayed.
+
+- **Allow Offline Access**: When this is enabled, Auth0 will allow applications to ask for Refresh Tokens for your API.
+
+- **Signing Algorithm**: The algorithm with which to sign the tokens. The available values are `HS256` and `RS256`. When selecting `RS256` (recommended), the token will be signed with your tenant's private key. This value is set when your API is created and cannot be modified afterwards. To learn more about signing algorithms, see [Signing Algorithms](/tokens/concepts/signing-algorithms).
diff --git a/articles/dashboard/reference/settings-application.md b/articles/dashboard/reference/settings-application.md
new file mode 100644
index 0000000000..3d7c8c4e10
--- /dev/null
+++ b/articles/dashboard/reference/settings-application.md
@@ -0,0 +1,112 @@
+---
+title: Application Settings
+description: Learn about the settings related to applications available in the Auth0 Dashboard.
+topics:
+ - api-authentication
+ - oidc
+ - applications
+ - dashboard
+contentType: reference
+useCase:
+ - add-login
+---
+# Application Settings
+
+On the [Applications](${manage_url}/#/applications) page of the [Auth0 Dashboard](${manage_url}/), locate your Application and click its name to view the available settings.
+
+## Basic Settings
+
+
+
+- **Name**: The name of your application. Editable, and will be seen in the portal, emails, logs, and so on.
+
+- **Domain**: Your Auth0 tenant name. You choose this when you create a new Auth0 tenant, and it cannot be changed. If you need a different domain, you must register for a new tenant by selecting **+ Create Tenant** in the top-right menu.
+
+- **Client ID**: The unique identifier for your application. You will use this when configuring authentication with Auth0. Generated by the system when you create a new application and cannot be modified.
+
+- **Client Secret**: A string used to sign and validate ID Tokens for authentication flows and to gain access to select Auth0 API endpoints. By default, the value is hidden, so check the **Reveal Client Secret** box to see it.
+
+::: warning
+While the Client ID is considered public information, the Client Secret **must be kept confidential**. If anyone can access your Client Secret, they can issue tokens and access resources they shouldn't be able to access.
+:::
+
+- **Description**: A free-text description of the Application's purpose. Maximum of 140 characters.
+
+- **Application Logo**: The URL to a logo (recommended size: 150x150 pixels) to be displayed for the application. Appears in several areas, including the list of applications in the Dashboard and customized consent forms.
+
+- **Application Type**: The [Auth0 application type](/applications). Determines which settings you can configure using the Dashboard. Not editable for M2M Apps. Sometimes disabled for other Auth0 application types if the selected grant types are only allowed for the currently selected application type.
+
+- **Token Endpoint Authentication Method**: Defines the requested authentication method for the token endpoint. Possible values are `None` (public client without a client secret), `Post` (client uses HTTP POST parameters), and `Basic` (client uses HTTP Basic). Only editable for Regular Web Apps and M2M Apps.
+
+::: note
+You can provide up to 100 URLs in the **Allowed Callback URLs**, **Allowed Web Origins**, **Allowed Logout URLs**, **Allowed Origins (CORS)** fields.
+:::
+
+- **Allowed Callback URLs**: Set of URLs to which Auth0 is allowed to redirect users after they authenticate. You can specify multiple valid URLs by comma-separating them (typically, to handle different environments like QA or testing). For production environments, verify that the URLs do not point to localhost. You can use the star symbol as a [wildcard for subdomains](/applications/reference/wildcard-subdomains) (`*.google.com`). Make sure to specify the protocol, `http://` or `https://`; otherwise, the callback may fail in some cases.
+
+- **Application Login URI**: In some scenarios Auth0 will need your application to start the OIDC login flow. This URI should point to a route in your application that starts the flow, by redirecting to the `/authorize` endpoint. It would usually take the form of 'https://myapp.org/login'. [Learn more](/universal-login/default-login-url).
+
+- **Allowed Web Origins**: List of URLs from where an authorization request using [`web_message` as the response mode](/protocols/oauth2#how-response-mode-works) can originate from. You can specify multiple valid URLs by comma-separating them. For production environments, verify that the URLs do not point to localhost.
+
+- **Allowed Logout URLs**: List of URLs to which you can redirect users after they log out from Auth0. Use the `returnTo` query parameter to redirect them. You can specify multiple valid URLs by comma-separating them. For production environments, verify that the URLs do not point to localhost. You can use the star symbol as a [wildcard for subdomains](/applications/reference/wildcard-subdomains) (`*.google.com`). Querystrings and hash information are not taken into account when validating these URLs. For more info, see [Logout](/logout).
+
+- **Allowed Origins (CORS)**: Set of URLs that will be allowed to make requests from JavaScript to Auth0 API (typically used with CORS). This prevents same-origin policy errors when using Auth0 from within a web browser. By default, all your callback URLs will be allowed; this field allows you to enter other origins if you need to. You can specify multiple valid URLs by comma-separating them. For production environments, verify that the URLs do not point to localhost. You can use the star symbol as a [wildcard for subdomains](/applications/reference/wildcard-subdomains) (`*.google.com`). Paths, querystrings, and hash information are not taken into account when validating these URLs (and may, in fact, cause the match to fail).
+
+- **ID Token Expiration (seconds)**: The amount of time (in seconds) before the Auth0 ID Token expires. The default value is `36000`, which maps to 10 hours.
+
+- **Use Auth0 instead of the IdP to do Single Sign-on**: If enabled, this setting prevents Auth0 from redirecting authenticated users with valid sessions to the identity provider (such as Facebook or ADFS). **Legacy tenants only.**
+
+## Advanced Settings
+
+The **Advanced Settings** section allows you to:
+
+* Manage or add Application Metadata, Device, OAuth, and WS-Federation settings
+* Obtain certificates and token endpoint information
+* Set the grant type(s) for the Application
+
+
+
+### Application Metadata
+
+Application metadata are custom string keys and values (each of which has a character maximum of 255), set on a per application basis. Metadata is exposed in the Application object as client_metadata, and in Rules as context.clientMetadata.
+
+You can create up to 10 sets of metadata.
+
+### Device Settings
+
+If you're developing a mobile application, you can provide the necessary iOS/Android parameters here.
+
+When developing iOS apps, you'll provide your **Team ID** and **App Bundle Identifier**.
+
+When developing Android apps, you'll provide your **App Package Name** and your **Key Hashes**.
+
+### OAuth
+
+Set the OAuth-related settings on this tab:
+
+* By default, all apps/APIs can make a delegation request, but if you want to explicitly grant permissions to selected apps/APIs, you can do so in **Allowed Apps/APIs**.
+
+* Set the algorithm used (**HS256** or **RS256**) for signing your JSON Web Tokens. For more info, see [Signing Algorithms](/tokens/concepts/signing-algorithms).
+
+* Toggle the **Trust Token Endpoint IP Header** setting; if this is enabled, the `auth0-forwarded-for` is set as trusted and used as a source of end user IP information for protection against brute-force attacks on the token endpoint. This setting is only available for Regular Web Apps and M2M Apps.
+
+* Toggle the switch to indicate if your application is **OIDC Conformant** or not. Applications flagged as OIDC Conformant will strictly follow the OIDC specification.
+
+* Set the location URL for **Cross-Origin Verification Fallback**. This is the location of the page that will be rendered inside an iframe to perform the token verification when third-party cookies are not enabled in the browser. Must be in the same domain where the embedded login form is hosted and must have an `https` scheme.
+
+### Grant Types
+
+Select grant types to enable or disable for your application. Available grant types are based on the application type.
+
+### WS-Federation
+
+Manage or add WS-Federation settings.
+
+### Certificates
+
+Manage or add the signing certificate, and its fingerprint and thumbprint.
+
+### Endpoints
+
+View endpoint information for OAuth, SAML, and WS-Fed.
+
diff --git a/articles/dashboard/reference/settings-tenant.md b/articles/dashboard/reference/settings-tenant.md
new file mode 100644
index 0000000000..baed139bae
--- /dev/null
+++ b/articles/dashboard/reference/settings-tenant.md
@@ -0,0 +1,173 @@
+---
+title: Tenant Settings
+description: Learn about the settings related to tenants available in the Auth0 Dashboard.
+toc: true
+topics:
+ - dashboard
+ - tenants
+contentType: reference
+useCase: manage-accounts
+---
+
+# Tenant Settings
+
+The [Tenant Settings](${manage_url}/#/tenant) page of the [Auth0 Dashboard](${manage_url}/) allows you to configure various settings related to your Auth0 tenant.
+
+## General
+
+The **General** tab contains settings that are typically set for tenants. Use this section to customize general tenant settings that will be used in the [Lock](https://auth0.com/lock) widget, emails, and various other pages displayed to your users.
+
+### Basic Settings
+
+
+
+* **Friendly Name**: Name you want displayed to your users, usually the name of your company or organization.
+* **Logo URL**: URL of your logo; it should be a square. This image will appear to your users on various screens and pages.
+* **Support Email**: Email address used to contact your support team.
+* **Support URL**: Link to your company/organization support page.
+
+### API Authorization Settings
+
+* **Default Audience**: API Identifier that should be the default audience when using [API Authorization](/api-auth) flows. If you enter a value, all [Access Tokens](/tokens/access-token) issued by Auth0 will specify this API Identifier as an audience.
+
+The Default Audience setting does not affect the [Client Credentials flow](/api-auth/tutorials/client-credentials). Clients will still need to provide an `audience` for these requests.
+
+::: note
+Setting the Default Audience is equivalent to appending this audience to every authorization request made to your tenant for every application. This will cause new behavior that might result in breaking changes for some of your applications. Please contact support if you require assistance.
+:::
+
+* **Default Directory**: Name of the connection to be used for [Password Grant exchanges](/api-auth/tutorials/password-grant). Its value should be the exact name of an existing [connection](/connections) for one of the following strategies: `auth0-adldap`, `ad`, `auth0`, `email`, `sms`, `waad`, or `adfs`.
+
+### Error Pages
+
+
+
+In the event of an authorization error, you can either display a generic error page to your users or you can redirect users to your own custom error page. To learn more, see [Custom Error Pages](/universal-login/custom-error-pages).
+
+### Languages
+
+* **Default Language**: Language your tenant will use by default.
+
+* **Supported Languages**: Languages also supported by your tenant.
+
+## Subscription
+
+
+
+The **Subscription** tab allows you to review your current subscription and compare features of your current plan to other Auth0 subscription plans. You may also change your subscription plan. To learn more, see [Changing Your Subscription](/support/subscription).
+
+## Payment
+
+The **Payment** tab allows you to enter or update your billing details.
+
+## Active Users
+
+**Active Users** functionality has been moved to the [Quota Utilization Report](https://support.auth0.com/reports/quota) in the Support Center.
+
+## Dashboard Admins
+
+The **Dashboard Admin** tab lists administrators assigned to your tenant. You may also add or remove tenant administrators and review whether administrator accounts have multi-factor authentication (MFA) enabled. To learn more, see [Manage Dashboard Admins](/tutorials/manage-dashboard-admins).
+
+## Webtasks
+
+<%= include('../../_includes/_webtask') %>
+
+The **Webtasks** tab describes how to build apps and extensions on top of [webtask.io](https://webtask.io/), which is used by the Auth0 rules engine.
+
+## Custom Domains
+
+The **Custom Domains** tab allows you to configure a custom domain, which allows you to maintain a consistent user experience. When a custom domain is configured, users will remain in your domain for login rather than being redirected to your *auth0.com* domain. To learn more, see [Custom Domains](/custom-domains).
+
+::: note
+Custom domains are not available for free plans. To configure a custom domain, you must upgrade your account to any paid plan.
+:::
+
+## Signing Keys
+
+The **Signing Keys** tab allows you to securely manage the signing key and certificate used to sign ID Tokens, Access Tokens, SAML assertions, and WS-Fed assertions that are sent to your applications.
+
+
+
+
+**Rotate Settings**: Settings that allow you to rotate the application signing key and certificate. You may choose whether or not to revoke the signing key upon rotation. To learn more, see [Manage Signing Keys](/tokens/guides/manage-signing-keys).
+ **Rotate Signing Key**: Rotates the signing key without revoking it; effectively, moves the current key to the previous key. All tokens signed with the previous key will still be valid until it is revoked.
+ **Rotate & Revoke Signing Key**: Rotates the signing key and then revokes it; effectively, moves the current key to the previous key and then invalidates the previous key. Make sure you have updated your application with the next key in queue before you rotate and revoke the current key.
+
+**List of Valid Keys**: List of valid application signing keys for your tenant, which are also available at the metadata endpoint for your application. Valid keys include:
+ * **Next in queue**: Key that will be used when the signing key is next rotated.
+ * **Currently used**: Key that is currently in use.
+ * **Previously used**: Key that was previously used. Its appearance indicates that the signing key has been rotated, but the previously-used key has not yet been revoked.
+
+**List of Revoked Keys**: List of the last three revoked keys for your tenant. More data about revoked keys is available via tenant logs.
+
+## Advanced
+
+The **Advanced** tab contains advanced settings that are sometimes set for tenants. On this tab, you can also delete your tenant and cancel all associated subscriptions.
+
+::: warning
+Deleted tenants cannot be restored and the tenant name cannot be used again when creating new tenants. If you want to change ownership of your tenant, see [Update Tenant Admin](/dashboard/manage-dashboard-admins#update-admin). If you want to reset your tenant configuration, see [Reset Tenants](/support/delete-reset-tenant#reset-tenants).
+:::
+
+### Login and Logout
+
+
+
+* **Allowed Logout URLs**: URLs that Auth0 can redirect to after logout when no `client_id` is specified on the logout endpoint invocation. Useful as a global list when Single Sign-on (SSO) is enabled. To learn more, see [Logout](/logout).
+
+* **Tenant Login URI**: URI that points to a route in your application that starts the OIDC login flow by redirecting to the `/authorize` endpoint; it should take the form of `https://mytenant.org/login`. This will only be used in scenarios where Auth0 needs your tenant to start the OIDC login flow. To learn more, see [Tenant Default Login URI](/universal-login/default-login-url).
+
+### Login Session Management
+
+These settings configure the login session lifetime, which represents the Auth0 Authorization Server session layer. The Authorization Server session layer drives Single Sign-on (SSO). To learn more, see [Single Sign-on](/sso).
+
+::: note
+Timeouts for tokens issued by Auth0 can be configured elsewhere. Token timeouts are often used to drive the Application session layer and appear in token claims, such as in the expiration claim for OpenID Connect (OIDC) ID Tokens or the lifetime assertion for SAML.
+:::
+
+
+
+* **Enable Seamless SSO**: When enabled, users will not be prompted to confirm log in before Single Sign-on (SSO) redirection.
+
+* **Inactivity Timeout**: Timeframe (in minutes) after which a user's session will expire if they haven’t interacted with the Authorization Server. Will be superseded by system limits if over 4,320 minutes (3 days) for Developer or Developer Pro or 144,000 minutes (100 days) for enterprise plans. To learn more, see [Single Sign-On](/sso).
+
+* **Require Login After**: Timeframe (in minutes) after which a user will be required to log in again, regardless of their activity. Will be superseded by system limits if over 43,200 minutes (30 days) for Developer or Developer Pro or 525,600 minutes (365 days) for enterprise plans.
+
+### Device Flow User Code Format
+
+If you are using the [Device Authorization Flow](/flows/concepts/device-auth), these settings configure the randomly-generated user code. To learn more, see [Call Your API from an Input-Constrained Device](/microsites/call-api/call-api-device#how-it-works).
+
+
+
+* **User Code Character Set**: Character set used to generate the user code.
+
+* **User Code Mask**: Mask used to format the user code. The mask defines the length of the user code and formats it into a friendly, readable value, allowing spaces or hyphens for readability.
+
+### Global Client Information
+
+
+
+The **Global Client ID** and **Global Client Secret** are used to generate tokens for legacy Auth0 APIs. Typically, you will not need these values. If you need to have the global client secret changed, please [contact support](https://support.auth0.com).
+
+### Settings
+
+
+
+* **Change Password Flow v2**: When enabled, the newest version of the Change Password Flow will be used. The previous version has been deprecated, and we strongly recommend enabling v2. This flag is presented only for backwards compatibility, and once enabled, you can no longer disable it. You can customize the user interface for the Change Password widget on the [Universal Login](${manage_url}/#/login_settings) > [Password Reset](${manage_url}/#/password_reset) tab in the [Auth0 Dashboard](${manage_url}).
+
+* **OIDC Dynamic Application Registration**: When enabled, third-party developers will be able to dynamically register applications for your APIs. You can also update this flag using the [Update tenant settings endpoint](/api/management/v2#!/Tenants/patch_settings) of the Auth0 Management API. By default, this feature is disabled. To learn more, see [Dynamic Client Registration](/api-auth/dynamic-client-registration).
+
+* **Enable Application Connections**: When enabled, all current [connections](/connections) will be enabled for any new [Application](${manage_url}/#/applications) that is created.
+
+* **Use a Generic Response in Public Signup API Error Message**: When enabled, errors generated while using the public signup API will return a generic response. This helps protect against user registration enumeration by preventing bad actors from being able to guess previously-registered email addresses or usernames from reading error response codes, such as `user_exists`.
+
+### Extensibility
+
+
+
+* **Runtime**: NodeJS version environment used to execute custom scripts that allow you to extend parts of Auth0's functionality; these include [Rules](/rules), [Hooks](/hooks), and [Database Connections](/connections#database-and-custom-connections). Choose the `node.js` version environment you will use to execute your custom scripts. If you are migrating from an older version of `node.js` that is no longer supported, see the [migration guide](/migrations/guides/extensibility-node12).
+
+### Migrations
+
+
+
+* **Disable Clickjacking Protection for Classic Universal Login**: When enabled, additional HTTP security headers will not be included in the response to prevent embedding of [Universal Login](/universal-login) prompts in an IFRAME.
diff --git a/articles/dashboard/reference/views-api.md b/articles/dashboard/reference/views-api.md
new file mode 100644
index 0000000000..efcd46026b
--- /dev/null
+++ b/articles/dashboard/reference/views-api.md
@@ -0,0 +1,25 @@
+---
+title: Auth0 Dashboard API Views
+description: Learn about the API Views available through the Auth0 Dashboard.
+topics:
+ - api-authentication
+ - oidc
+ - apis
+ - dashboard
+contentType: reference
+useCase:
+ - secure-api
+ - call-api
+---
+
+# Dashboard Views for APIs
+
+Available views for your API include:
+
+- **Settings**: lists the settings for your API, some of which are editable. In this section, you can change the token expiration time and enable offline access (so that Auth0 will allow applications to ask for Refresh Tokens for this API). For details, see [API Settings](/api-auth/references/dashboard/api-settings).
+
+- **Scopes**: allows you to [define the scopes](/scopes/current/guides/define-scopes-using-dashboard) for your API by setting scope names and descriptions. For more details, see [API Scopes](/scopes/current/api-scopes).
+
+- **Machine to Machine Applications**: lists all applications for which the **Client Credentials** grant is **enabled**. (By default, this grant is **enabled** for [Regular Web Applications and Machine to Machine Applications](/applications). You can authorize any listed application to request Access Tokens for your API. Optionally, you can select a subset of the defined scopes to limit an authorized application's access to your API.
+
+- **Test**: allows you to execute a sample Client Credentials flow with any of the authorized applications so you can check that everything is working as expected.
diff --git a/articles/deploy/checklist.md b/articles/deploy/checklist.md
new file mode 100644
index 0000000000..2be26ecd1b
--- /dev/null
+++ b/articles/deploy/checklist.md
@@ -0,0 +1,27 @@
+---
+title: Deploy Checklist
+description: Deployment checklists for your implementation.
+topics:
+ - SDLC
+ - checklists
+ - best practices
+ - implementation checklist
+contentType: reference
+useCase:
+ - implementation
+---
+# Deploy Checklist
+
+Auth0 has provided the following deployment checklist for your use. You may not find that every item is applicable, so please modify the checklist based on the needs of your implementation.
+
+## How to use the checklist
+
+1. Click the links below to download each checklist.
+2. Open the checklist in any spreadsheet application.
+3. Customize the checklist to suit your needs.
+
+ [Deploy Checklist](/media/articles/architecture-scenarios/checklists/Deploy-Checklist.xlsx)
+
+In the Deploy phase, you will deploy the system to either a staging or production environment, where actual users begin to operate and interact with it.
+
+Eventually, you deploy all components of the system to the production environment when you make a live release.
\ No newline at end of file
diff --git a/articles/deploy/index.md b/articles/deploy/index.md
new file mode 100644
index 0000000000..deabc126f6
--- /dev/null
+++ b/articles/deploy/index.md
@@ -0,0 +1,29 @@
+---
+classes: topic-page
+title: Deploy
+description: Information about deploying Auth0
+topics:
+ - deploy
+contentType:
+ - index
+---
+# Deploy
+
+The following pages will cover everything you need to know about deploying Auth0. In addition to covering deployment models, we'll provide you with pre-deployment tips, tricks, and tests, as well as an extension to make multi-environment deployments easier.
+
+
Get pre-launch tips and tricks, and learn how to use Auth0's pre-deployment testing suite to make sure that you've completed all necessary tasks prior to go live.
The Deploy CI Extension is helpful for multi-environment deployments and can be used to support integration into existing CI/CD pipelines.
+
\ No newline at end of file
diff --git a/articles/design/browser-based-vs-native-experience-on-mobile.md b/articles/design/browser-based-vs-native-experience-on-mobile.md
index 13ec0ce280..1fba03742b 100644
--- a/articles/design/browser-based-vs-native-experience-on-mobile.md
+++ b/articles/design/browser-based-vs-native-experience-on-mobile.md
@@ -2,27 +2,32 @@
title: Browser-Based vs. Native Login Flows on Mobile Devices
description: This article covers the pros and cons between a browser-based vs. native experience when implementing Auth0 on a mobile device
toc: true
+topics:
+ - design
+ - mobile
+contentType: reference
+useCase: strategize
---
# Browser-Based vs. Native Login Flows on Mobile Devices
-When developing a native application, such as an app running on iOS or Android, you can choose between the following login flows: **native**, or **browser-based**.
+When developing a native mobile application, such as an iOS or Android application, you can choose between the following login flows: **native**, or **browser-based**.

-When using a **browser-based** login flow, iOS opens a SafariViewController, whereas Android opens up a Custom Chrome Tab. The user is redirected to the Auth0 login page, where they can either sign up or log in.
+When using a **browser-based** login flow, the user is shown a web browser and redirected to the Auth0 login page, where they can either sign up or log in. For example, an iOS application opens a SafariViewController or Android application opens a Custom Chrome Tab.
-When using a **native** login flow, the user signs up or enters their credentials directly into the app.
+When using a **native** login flow, the user signs up or enters their credentials directly into the app.
-This article discusses the things you need to consider, before you decide whether you will opt for a browser-based, or a native login flow.
+The rest of this article discusses more things to consider, before you decide on a browser-based, or a native login flow.
-## SSO across native applications
+## Single Sign-on across native applications
-If you have a suite of mobile applications (such as Google Drive, Google Docs/Sheets, YouTube, and so on), you might want to automatically log the user into all of them if they log into any one app.
+If you have several mobile applications (such as Google Drive, Google Docs/Sheets, YouTube, and so on), you might want to automatically log the user into all of them if they log into any one app.
-If your suite uses a wholly native experience, your users have to enter their credentials for each of your apps. However, if you use a browser-based UX, you can implement SSO to reduce the number of times the user has to log in.
+If your applications use a wholly native experience, your users have to enter their credentials for each application. However, if you use a browser-based login flow you can implement Single Sign-on (SSO), reducing the number of times the user has to log in.
::: note
-You can implement SSO with native apps by storing Refresh Tokens on a shared keychain, but this technique is not compliant with the OAuth 2.0 specifications.
+You can implement SSO with native apps by storing Refresh Tokens on a shared keychain, but this technique is not compliant with the OAuth 2.0 specifications.
:::
## SSO across devices/desktops/laptops
@@ -33,37 +38,35 @@ While SmartLock is not yet universal, using browser-based login flows allows you
## Phishing and security issues
-With a native login flow, there's no way to avoid an unauthorized party from decompiling or intercepting traffic to/from your app to obtain the Client ID and authentication URL. Using these pieces of information, the unauthorized party can then create a rogue app, upload it to an app store, and use it to phish users for the username/passwords and Access Tokens.
+With a native login flow, an unauthorized party could decompile or intercept traffic to/from your application to get the Client ID and authentication URL. With this information the unauthorized party could create a rogue application, upload it to an application store, and use it to phish for usernames, passwords, and Access Tokens.
-Using a browser-based flow protects you from this, since the callback URL is linked to the app through [universal app links](https://developer.apple.com/ios/universal-links/) (iOS) or [App Links](/applications/enable-android-app-links) (Android). Note, however, that this is **not** a universally supported feature.
+Using a browser-based flow protects you from this, since the callback URL is linked to the application through [universal app links](https://developer.apple.com/ios/universal-links/) (iOS) or [App Links](/dashboard/guides/applications/enable-android-app-links) (Android). Note, however, that this is **not** a universally supported feature.
## Implementation time
-Using browser-based flows reduces the implementation time required, since everything is handled by the login page (including multifactor authentication and anomaly detection).
+Using browser-based flows reduces the implementation time required, since everything is handled by the hosted login page (including multi-factor authentication and anomaly detection).
-By default, [Lock](/libraries/lock) provides the UX, but you can customize it completely by providing your own UX written in HTML/CSS and integrating it with [auth0.js](libraries/auth0js)
+By default, [Lock](/libraries/lock) provides the user experience, but you can customize it with your own templates written in HTML and CSS, then integrate it with [auth0.js](libraries/auth0js)
## Automatic improvements
-By relying on a universal login experience, you will automatically receive new features without requiring you to make any changes to your native application. For example, if Auth0 adds support for FIDO/U2F, you would not need to make any code changes to your app before you can use this functionality.
+By relying on a Universal Login experience, you will automatically receive new features without requiring you to make any changes to your native application. For example, if Auth0 adds support for [FIDO/U2F](https://www.yubico.com/solutions/fido-u2f/), you would not need to make any code changes to your application before you can use this functionality.
## Load time and user experience
-When using a native login flow, the login UI and logic is embedded onto the app bundle. Conversely, with a browser-based login flow, the user sees some loading time as the page loads.
+When using a native login flow, the login UI and logic is included in the application. With a browser-based login flow, the user sees some loading time as the page loads.
-However, it's worth noting that the number of times a user logs in with the mobile devices most commonly used today is low. Once the user logs in, your app should only log them out if you revoke their access or if the user opts to log out.
+However, it's worth noting that the number of times a user logs in with the mobile devices is low. Once the user logs in, your application should only log them out if you revoke their access or if the user opts to log out.
## Compliance with best practices
-As explained in the [RFC 8252 OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252), OAuth 2.0 authorization requests from native apps should only be made through external user-agents, primarily the user's browser. The specification details the security and usability reasons why this is the case.
-
-::: note
-For an overview of RFC 8252, refer to [OAuth 2.0 Best Practices for Native Apps](https://auth0.com/blog/oauth-2-best-practices-for-native-apps).
-:::
+As explained in the [RFC 8252 OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252), OAuth 2.0 authorization requests from native apps should only be made through external user-agents, primarily the user's browser. The specification details the security and usability reasons why this is the case.
## Conclusion
-There are upsides and downsides to using either a browser-based or native login flow on mobile devices, but regardless of which option you choose, Auth0 supports either.
+If your platform supports it, you should use a **browser-based** login flow where your application presents an in-application (embedded) browser for login and signup. Using an in-application browser gives your application the benefits of browser-based authentication, such as shared authentication state and security context, without disrupting the user experience by switching applications.
+
+Regardless of which option you choose, Auth0 supports either.
## Implementation examples
diff --git a/articles/design/creating-invite-only-applications.md b/articles/design/creating-invite-only-applications.md
index 795efd66cd..d07173f3c6 100644
--- a/articles/design/creating-invite-only-applications.md
+++ b/articles/design/creating-invite-only-applications.md
@@ -1,114 +1,73 @@
---
-description: How to customize the signup process for an invite-only application with Auth0
+description: Describes how to customize the signup process for an invite-only application with Auth0.
toc: true
crews: crew-2
+topics:
+ - design
+contentType: how-to
+useCase: invite-only
---
-# Invite-Only Applications
+# User Invitation Applications
-Many SaaS apps allow self-service provisioning, where users can register themselves and begin using the app. Other types of apps, however, do not allow such signups. Instead, the customer (typically an organization of some type) pay upfront for a number of users, and only the end user with the appropriate credentials may sign up and access the app. In such cases, you can use an invite-only workflow for authorization purposes.
+You can restrict users signups to an application. One way to do this is with user invitations as a provisioning workflow, either in conjunction with or as an alternative to self-provisioning. In this case, an administrator creates the user accounts then invites users to complete the signup process by creating passwords for those accounts. The user experience consists of the following steps:
-## Example Scenario: ExampleCo
+1. User receives an email inviting them to register.
+2. User follows a link to the **Set Up Password** page.
+3. User creates and verifies a password.
+4. User signs in.
+5. User has access to the target application.
-In this tutorial, we will work through a sample setup for the fictional company, ExampleCo.
+A user invitation is basically a change password link repurposed as an invitation. There are two common approaches for this:
-ExampleCo is a multi-tenant SaaS solution offering cloud-based analytics. Customers purchasing licenses send ExampleCo lists of users whom they want to access the application.
+* Send an Auth0 [change password email](/email/custom#change-password-confirmation-email) using a [customized email template](/email/templates)
+* Create a password change ticket
-You can handle this requirement in Auth0 using an [Enterprise Connection](/identityproviders#enterprise) (using federation) with the individual customers using ADFS, SAML-P, and so on. This allows the customer to authenticate users with their own Active Directory specifying who gets access to the app.
+## Generate invitations
-The invite-only authorization flow includes the following steps:
+You can allow a user to access an existing account that you have created on their behalf. Then, send the user a unique link to set their password. You generate the unique link by creating a Password Change ticket where your invitation app calls the /password-change Management API endpoint. You will need to:
-1. Creating new users in ExampleCo and bulk importing the same users into Auth0
-1. Triggering the email verification process via Auth0
-1. Triggering the password reset process via Auth0
+* Create an [Auth0 database](/connections/database) user with the `user.email_verified` parameter set to `false`
+* Have access to an [external email service](/email/providers)
+* Obtain a [Management API access token](/api/management/v2/tokens)
-### Setup your Application
+### Create Password Change tickets
-You can store all ExampleCo end users in a single database, since everyone will provide their unique corporate email addresses.
+1. Specify the user using `user_id` or `email` and `connection_id`.
+2. Specify where the user will be redirected. The `result_url` parameter is the location the user will be redirected to once they have set their password. In this case, this should be back to the target app login page. See [Redirect Users to other URLs](/users/guides/redirect-users-after-login#redirect-users-to-other-urls) for details.
+3. Specify the lifespan of the invitation link. Use the `ttl_sec` parameter to set how long the invitation link will remain active. This should align with your relevant security concerns. The link is one time use, so once the user has set their password, it is not vulnerable to reuse.
+4. Verify the email address. As long as this invitation is being sent to the email registered to the account, you should set the email as `verified` once the user has set their password. Use the `mark_email_as_verified` parameter as `true`. If this invitation is sent to anywhere other than the user's registered email address, you **should not** set the email verification to `true`. A successful request to this endpoint will result in a ticket URL to be returned. The URL will then be used to create the user invitation.
-
+### Add query parameters to the ticket URL
-To prevent users from signing themselves up and adding themselves to the database connection, be sure to select the **Disable Sign Ups** option on the connection to make sure users can only be created on the backend.
-
-You will need to create a [application](/applications) in the [Dashboard](${manage_url}/#/applications) with the correct parameters:
+The query parameters are used to customize the password reset UI. The returned URL will have the unique code value that allows the user to set their password followed by a `#`. For the link to work, you do not want to edit anything before the hash.
- - **Name**: give your application a clear name as this will be used in the emails being sent out during the invite-only workflow
- - **Application Type**: this will be a regular web application.
- - **Allowed Callback URLs**: this should be the URL of your app
+1. Add hash parameters to the generated password ticket URL.
+2. Add a parameter to identify that the UI should represent a set password workflow rather than a change password workflow.
+3. Add a parameter to identify the target app in the case that invites might be sent for more than one app.
-
+### Create an email template
-Since this application needs to access the [Management API](/api/v2), you'll need to authorize it and set its scopes as follows:
+The email invitation needs to be sent with your existing email service provider. The language in the email should align with your use case. Include the link generated from the steps above. The text in the email should explain:
+* The next steps to claiming the user account.
+* The expiration of the link.
+* Steps to generate a new invite if it has expired.
-* Go to the [APIs section](${manage_url}/#/apis) of the Dashboard.
-* Select **Auth0 Management API**.
-* Click over to the **Machine to Machine Applications** tab.
-* Find the application you just created, and set its toggle to **Authorized**.
-* Use the **down arrow** to open up the scopes selection area. Select the following scopes: `read:users`, `update:users`, `delete:users`, `create:users`, and `create:user_tickets`.
-* Click **Update**.
+## Customize the Password Reset UI
-
+Once the user clicks the link in the invitation they will be brought to the [Universal Login Password Reset](/universal-login/password-reset) page. Here they will set a password for their account. Since this page is used both for the forgot password workflow and for your user invitations, you will want to use the query parameters you defined earlier to identify the invite workflow and customize the UI accordingly.
-### Import Users
+## Complete the user experience
-Every user that exists in ExampleCo should be created in your Auth0 database connection as well. Auth0 offers a [bulk user import functionality](/users/bulk-importing-users-into-auth0) for this purpose.
+In most cases, once the user has set their password, you grant them access to the target app. The target app initiates the login sequence with the following steps:
-### Email Verification
+1. User submits password.
+2. Change password screen redirects return URL.
+3. Target app redirects to /authorize.
+4. User submits their credentials.
+5. User is authenticated into the app.
-Once you've created the user in Auth0, you'll send the appropriate `POST` call from your app to the [Create an Email Verification Ticket endpoint](/api/management/v2#!/Tickets/post_email_verification) to trigger an email that verifies the user's email.
+The workflow involves redirects but it is possible for the transition from the set password form to the login form to appear seamless to the end user.
-Be sure to update the following placeholder values:
+The `return_url` you set when you created the Password Change ticket is where the user will be redirected after creating their password. In this case you want the URL to be on the site the user has been invited to so that it can initiate the login workflow. Your target app will need to parse the `success` parameter to confirm no errors occurred then immediately initiate the redirect back to Auth0 to log the user in.
-* `MGMT_API_ACCESS_TOKEN`: replace with your [API Access Token](/api/management/v2/tokens)
-* `YOUR_APP_CALLBACK_URL`: replace with the callback/return URL for your app
-* `USER_ID`: replace with the Auth0 user ID for the end user
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/api/v2/tickets/email-verification",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [{
- "name": "Authorization",
- "value": "Bearer MGMT_API_ACCESS_TOKEN"
- }],
- "queryString": [],
- "postData": {
- "mimeType": "application/json",
- "text": "{ \"result_url\": \"YOUR_APP_CALLBACK_URL\", \"user_id\": \"USER_ID\", \"ttl_sec\": 0 }"
- },
- "headersSize": -1,
- "bodySize": -1,
- "comment": ""
-}
-```
-
-### Password Reset
-
-Once you've verified the user's email, you will need to initiate the [password change process](/connections/database/password-change). To do so, your app should make a `POST` request to Auth0's Management API.
-
-Be sure to replace the placeholder values for your [API Access Token](/api/management/v2/tokens), as well as those within the body of the call, including the callback/return URL for your app and the user's details.
-
-```har
-{
- "method": "POST",
- "url": "https://${account.namespace}/api/v2/tickets/password-change",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [{
- "name": "Authorization",
- "value": "Bearer MGMT_API_ACCESS_TOKEN"
- }],
- "queryString": [],
- "postData": {
- "mimeType": "application/json",
- "text": "{ \"result_url\": \"YOUR_APP_CALLBACK_URL\", \"user_id\": \"USER_ID\", \"new_password\": \"secret\", \"connection_id\": \"con_0000000000000001\", \"email\": \"EMAIL\", \"ttl_sec\": 0 }"
- },
- "headersSize": -1,
- "bodySize": -1,
- "comment": ""
-}
-```
-
-## Summary
-
-This tutorial walked you through implementing an invite-only sign-up flow using the [Management API](/api/v2) to customize the sign-up process and the email handling.
+To optimize the user experience, you can have the target app parse the `email` parameter and include it with the authentication request as the `login_hint` parameter. This will prefill the user's email in the login form.
\ No newline at end of file
diff --git a/articles/design/index.md b/articles/design/index.md
index 3f3fc63b99..83015636a5 100644
--- a/articles/design/index.md
+++ b/articles/design/index.md
@@ -2,6 +2,12 @@
title: Design Your Auth0 Implementation
description: Guidance for designing your Auth0 implementation
classes: topic-page
+topics:
+ - design
+contentType:
+ - index
+ - how-to
+useCase: strategize
---
- Using Auth0 with invite-only applications, which are those where access is limited to a select group of previously-identified users.
+ Using Auth0 with applications where an administrator creates the user account and then invites the user to complete the signup process by setting a password.
diff --git a/articles/design/using-auth0-with-multi-tenant-apps.md b/articles/design/using-auth0-with-multi-tenant-apps.md
index 2e7057a9b3..3aa8e483a1 100644
--- a/articles/design/using-auth0-with-multi-tenant-apps.md
+++ b/articles/design/using-auth0-with-multi-tenant-apps.md
@@ -1,44 +1,72 @@
---
-description: This articles discusses how you can use Auth0 with multi-tenant applications.
+description: This article discusses how you can use Auth0 to secure multi-tenant applications.
crews: crew-2
toc: true
+topics:
+ - design
+ - multi-tenancy
+contentType: concept
+useCase: strategize
---
-# Using Auth0 with Multi-Tenant Applications
-In this article, we will discuss (at a high-level) how Auth0 can help you manage users for your multi-tenant applications.
+# Using Auth0 to Secure Your Multi-Tenant Applications
-Multi-tenancy refers to the software architecture principle where a single instance of software runs on a server that is accessible to multiple groups of users.
+This article provides a high-level overview of how Auth0 can help you manage your multi-tenant applications.
-When working with multi-tenant software, you can serve multiple customers from a single application instance running on one server (or pool of servers). This contrasts with single-tenant software, where you serve each customer with a dedicated software instance running on dedicated servers. In summation:
+## What is multi-tenancy
-| Tenancy Type | Definition |
-| - | - |
-| Multi-Tenant | One instance, multiple customers |
-| Single-Tenant | One instance, one customer |
+[Multi-tenancy](https://en.wikipedia.org/wiki/Multitenancy) is when a single instance of software runs on a server that is accessible to multiple groups of users.
-We define **tenant** as a group of users who share access to one particular application instance. One example of this includes a company with multiple employees, all of whom have access to your SaaS offering.
+Auth0's Public Cloud is an example of a multi-tenant application. Your applications, settings, and connections are a single tenant, which shares resources with other tenants in the Public Cloud.
-When you use a multi-tenant setup, one single instance of your SaaS offering would be shared across multiple tenants (or multiple companies), each of whom has its own group of employees. However, each tenant has a dedicated share of that instance, and you can then customize each share to meet the needs of the tenant that's using it. Such customization includes (but isn't limited to) branding, functionality, and access control.
+Please note that this article is **not about using multiple Auth0 tenant(s)**. It is about using Auth0 to secure your own multi-tenant application.
-## Auth0 and Multi-Tenancy
+## Auth0 and multi-tenancy
-By using a single Auth0 tenant for all of *your* customers, you maintain simplicity in your architecture and are able to manage all of your authentication flows in one place. The primary method by which you can handle multi-tenancy is to use multiple [connections](identityproviders).
+There are several ways you can secure multi-tenant applications with Auth0. You can handle your multi-tenancy needs with one of the following approaches:
-::: note
-We recommend that you [create multiple Auth0 tenants](https://github.com/auth0/auth0-multitenant-spa-api-sample) only if you need to share access to the Auth0 Dashboard with individual customers.
-:::
+* [Use multiple connections](#use-multiple-connections)
+* [Identify different tenants by application](#identify-tenants-by-application)
+* [Store tenant details in app_metadata](#store-tenant-details-in-app_metadata)
+* [Use separate Auth0 tenants](#create-separate-auth0-tenants-for-each-customer)
-## Use Multiple Connections
+### Use multiple connections
+
+You can use multiple connections to handle your tenants. Each connection would represent and contain a different pool of users.
::: warning
-Auth0 enforces a limit of 50 Database Connections for each [application](/applications). Users with Enterprise agreements do not have any Database Connections limits.
+If you use [Lock](/libraries/lock) in your applications, Lock supports a maximum of **50 Database Connections** per [application](/applications). Enterprise Connections are not affected by this limit. If you use the New Universal Login Experience, Lock is not involved and this limitation therefore does not affect you.
:::
-While using multiple [Connections](/identityproviders) introduces additional layers of complexity, there are several scenarios where this option might make sense:
+Using multiple [Connections](/identityproviders) introduces additional layers of complexity, but there are several scenarios where the upsides of this option outweigh the downsides:
* You have different Connection-level requirements, such as varying password policies, for each of your Applications.
-* You have users from different Connections. For example, one app may have users providing username/password credentials, while another app handles Enterprise logins.
+* You have user pools from different Connections. For example, one app may have users providing username/password credentials, while another app handles Enterprise logins.
+
+To implement this, you can call `/authorize` with a connection specified for the user, using the `connection` option in the [Auth0 SPA SDK](/libraries/auth0-spa-js), or by passing a `connection` parameter to the `authorize()` method in [Auth0.js](/libraries/auth0js/v9).
::: note
-For additional assistance on how you can customize Auth0, please contact [Sales](https://auth0.com/?contact=true) to discuss possible architecture scenarios.
+There are entity limits which may apply when using Auth0 libraries. See [Entity Limit Policy](/policies/entity-limits) for details.
:::
+
+### Identify tenants by application
+
+You can represent each of your tenants with a separate application in Auth0.
+
+Representing each of your tenants with an application allows you to configure each one differently. You can also enable/disable [connections](/connections) for individual applications if your tenants have varying requirements. Doing so, however, requires you to track the tenants to which your users belong within your application. Then, when they log in, you will need to specify the application they are to use.
+
+### Store tenant details in app_metadata
+
+Storing tenant details in the user [metadata](/users/concepts/overview-user-metadata#metadata-usage) is the simplest of the implementation scenarios we cover in this article.
+
+Using the identifier of your choice (e.g., `"tenant": "customer_12345"`), you can store tenant related details in the `app_metadata`. Doing so allows all of your users, regardless of which tenant to which they belong, to log in using one uniform method.
+
+You can check for this value in your application after users log in and are redirected. This will help you sort users.
+
+### Create separate Auth0 tenants for each customer
+
+You can create a new Auth0 tenant for each of your application's tenants.
+
+We recommend that you follow this approach only if you need to share access to the Auth0 Dashboard with individual customers. Otherwise, one of the above solutions is a more practical and easy to manage one than attempting to manage many Auth0 tenant dashboards, which is also not a scalable solution as your customer base grows.
+
+This method requires you to use a different set of Auth0 credentials when calling Auth0 APIs to authenticate users belonging to each customer, because you would be using different applications on different Auth0 tenants (with different Client IDs) for each of your customers.
diff --git a/articles/design/web-apps-vs-web-apis-cookies-vs-tokens.md b/articles/design/web-apps-vs-web-apis-cookies-vs-tokens.md
index d59ca69e09..534c8d6a6f 100644
--- a/articles/design/web-apps-vs-web-apis-cookies-vs-tokens.md
+++ b/articles/design/web-apps-vs-web-apis-cookies-vs-tokens.md
@@ -1,15 +1,19 @@
---
description: This page compares web applications to web APIs and cookies vs. Tokens.
+topics:
+ - design
+ - web-apps
+ - cookies
+ - tokens
+ - apis
+contentType: concept
+useCase: strategize
---
# Web Apps vs Web APIs / Cookies vs Tokens
* For us **Web Apps** are the traditional server-side applications that use **cookie-based authentication**.
-* **Web APIs**, on the other hand, represent for us a new breed of applications, typically single page apps (like Angular, Ember, Backbone, and so on) or native mobile apps (like iOS, Android, and so on) which consume APIs (written in Node, Ruby, ASP.NET or even a mix of those) and will benefit from **token based authentication**.
-
-::: note
-Before moving forward, you might want to read these articles for more context: [Cookies vs Tokens. Getting auth right with Angular.JS](https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/) and [10 Things You Should Know about Tokens](https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/).
-:::
+* **Web APIs**, on the other hand, represent for us a new breed of applications, typically single-page apps (like Angular, Ember, Backbone, and so on) or native mobile apps (like iOS, Android, and so on) which consume APIs (written in Node, Ruby, ASP.NET or even a mix of those) and will benefit from **token based authentication**.
* **Cookie-based authentication** is implemented by each web platform differently, but at the end of the day, they all end up setting some cookie (tied to a session on the server) which represents the "authenticated user". On each request, that cookie is sent and the session is deserialized from some store (in memory if it's a single server or some persistent storage if it's a server farm). We provide SDKs for most of the platforms that will tie into the corresponding authentication subsystem (such as passport on node, IPrincipal on .NET or Java, and so on).
@@ -17,6 +21,8 @@ Before moving forward, you might want to read these articles for more context: [
* For both approaches you can get the **same amount of information from the user**. That's controlled by the `scope` parameter sent in the login request (either using the [Auth0Lock](/lock), our [JavaScript library](https://github.com/auth0/auth0.js) or a plain link). The `scope` is a parameter of the `.signin({scope: 'openid name email'})` method which ends up being part of the querystring in the login request. You can get more details about this in the [Scopes Documentation](/scopes).
-* By default we use `scope=openid` in **token-based authentication** to avoid having a huge token. You can control any [standard OpenID Connect claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) that you want to get in the token by adding them as scope values. For example, `scope=openid name email family_name address phone_number`.
+* By default we use `scope=openid` in **token-based authentication** to avoid having a huge token. You can control any [standard OpenID Connect (OIDC) claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) that you want to get in the token by adding them as scope values. For example, `scope=openid name email family_name address phone_number`.
+
+* Finally, you can **mix token-based authentication** with **cookie-based authentication**. Take into account that cookies will work just fine if the web app and the API are served from the same domain, so you might not need token based authentication. Now, if you need to, we also return a JWT on the web app flow. Each of our SDKs will do it differently. If you want to call your APIs from JavaScript (instead of using the existing cookie), then somehow you have to set the ID Token in your webpage. One way of doing it is by setting it on your layout/master page--something like `window.token = ${"<%= id_token %>;"}`--and then getting it from anywhere in your JavaScript code.
-* Finally, you can **mix token-based authentication** with **cookie-based authentication**. Take into account that cookies will work just fine if the web app and the API are served from the same domain, so you might not need token based authentication. Now, if you need to, we also return a JWT on the web app flow. Each of our SDK will do it differently. If you want to call your APIs from JavaScript (instead of using the existing cookie) then somehow you have to set the `id_token` in your webpage. One way of doing it is by setting it on your layout/master page something like `window.token = ${"<%= id_token %>;"}` and then you get it from anywhere in your JavaScript code.
+<%= include('../_includes/_samesite_none') %>
\ No newline at end of file
diff --git a/articles/dev-centers/java.md b/articles/dev-centers/java.md
index e385db98ab..7d3e89fcb1 100644
--- a/articles/dev-centers/java.md
+++ b/articles/dev-centers/java.md
@@ -2,6 +2,10 @@
title: Java Developer Center
description: Resources and documentation for Java developers
logo: java
+topics:
+ - java
+contentType: reference
+useCase: strategize
---
# Java SDK Developer Center
@@ -10,7 +14,7 @@ Here at Auth0 we try to offer as many libraries as needed to ensure we make your
## Java Servlet
-A simple servlet based solution, suitable if you are using a legacy application or alternate Web MVC Framework without Spring support. If your application only needs secured endpoints and the ability to programmatically work with a Principal object for GrantedAuthority checks this library is a good fit.
+A simple servlet based solution, suitable if you are using a legacy application or alternate Web MVC Framework without Spring support. If your application only needs secured endpoints and the ability to programmatically work with a Principal object for GrantedAuthority checks, this library is a good fit.
- [Documentation](/server-platforms/java)
- [Library](https://github.com/auth0/auth0-servlet)
@@ -22,9 +26,8 @@ A modern Java Spring library that allows you to use Auth0 with Java Spring for s
- [Documentation](/server-platforms/java-spring-mvc)
- [Library](https://github.com/auth0/auth0-spring-mvc)
-- [Sample Project](https://github.com/auth0-samples/auth0-spring-mvc-sample): Simple sample project that demonstrates using Auth0 with Java Spring to create a Secured MVC Web Application.
-- [Sample Project demonstrating Lock, auth0.js, Social Connection Login, Database Connection and Account Linking](https://github.com/auth0-samples/auth0-spring-boot-social-dbconnection-link): Extends the simpler [Auth0 Spring MVC Sample Project](https://github.com/auth0-samples/auth0-spring-mvc-sample) and demonstrates Social Login, Database Connection Login and [account linking](/link-accounts). In this app, you can choose to login either with a Social Login or a Database Connection. If you login using Social Login and have not already linked you DB Connection then you are requested to do so. You can find details on how to setup and use this sample application in the _README_ of the [GitHub repository](https://github.com/auth0-samples/auth0-spring-boot-social-dbconnection-link).
-- [Sample Project demonstrating Passwordless Authentication, Multifactor Authentication opt-in & account linking](https://github.com/auth0-samples/auth0-spring-mvc-passwordless-mfa-sample): Extends the simpler [Auth0 Spring MVC Sample Project](https://github.com/auth0-samples/auth0-spring-mvc-sample) and demonstrates using Auth0 (including Lock Passwordless and Auth0.js) with Java Spring to create a Secured MVC Web Application using [Passwordless Authentication](/connections/passwordless), [Multifactor Authentication](/multifactor-authentication) Opt-in & [account linking](/link-accounts). You can find details on how to setup and use this sample application in the _README_ of the [GitHub repository](https://github.com/auth0-samples/auth0-spring-mvc-passwordless-mfa-sample.
+- [Sample Project](https://github.com/auth0-samples/auth0-spring-mvc-sample): A simple sample project that demonstrates usage of Auth0 with Java Spring to create a Secured MVC Web Application.
+- [Sample Project demonstrating Lock, auth0.js, Social Connection Login, Database Connection and Account Linking](https://github.com/auth0-samples/auth0-spring-boot-social-dbconnection-link): Extends the simpler [Auth0 Spring MVC Sample Project](https://github.com/auth0-samples/auth0-spring-mvc-sample) and demonstrates Social Login, Database Connection Login and [account linking](/users/concepts/overview-user-account-linking). In this app, you can choose to login either with a Social Login or a Database Connection. If you login using Social Login and have not already linked your DB Connection, then you are requested to do so. You can find details on how to setup and use this sample application in the _README_ of the [GitHub repository](https://github.com/auth0-samples/auth0-spring-boot-social-dbconnection-link).
## Java Spring Security MVC
@@ -35,32 +38,32 @@ A modern Java Spring library that allows you to use Auth0 with Spring Security f
- [Sample Project](https://github.com/auth0-samples/auth0-spring-security-mvc-sample)
::: panel Authorization Code Grant
-All three technologies displayed above, adopt the `Oauth2 / OIDC Authorization Code Grant` flow in which authentication results in a callback to the server-side application with a `code`. This is then exchanged for [id_token](/tokens/id_token) and [access_token](/tokens/access_token) on the server-side (as part of the callback), and once the tokens have been received by the application, then `UserProfile` information can also be retrieved via request with a valid Token.
+All three technologies displayed above, adopt the `Oauth2 / OIDC Authorization Code Grant` flow in which authentication results in a callback to the server-side application with a `code`. This is then exchanged for [ID Token](/tokens/id_token) and [Access Token](/tokens/access_token) on the server-side (as part of the callback) and once the tokens have been received by the application, then `UserProfile` information can also be retrieved via request with a valid Token.
:::
## Java Spring Security API
-A modern Java Spring library that allows you to use Auth0 with Spring Security. Leverages Spring Boot dependencies. Validates the JWT from Auth0 in every API call to assert authentication according to configuration. This library would be suitable for headless APIs and SPA (single page application) backend end server scenarios.
+A modern Java Spring library that allows you to use Auth0 with Spring Security. Leverages Spring Boot dependencies. Validates the JWT from Auth0 in every API call to assert authentication according to configuration. This library would be suitable for headless APIs and SPA (single-page application) backend end server scenarios.
- [Documentation](/server-apis/java-spring-security)
- [Library](https://github.com/auth0/auth0-spring-security-api)
- [Sample Project](https://github.com/auth0-samples/auth0-spring-security-api-sample)
-- [Companion SPA Applications](https://github.com/auth0-samples/auth0-spring-security-api-client-samples): Sample application that works as a companion for the [Auth0 Spring Security API Sample](https://github.com/auth0-samples/auth0-spring-security-api-sample) and [Auth0 Spring Security API Resource Server Sample](#auth0-resource-server-sample-using-spring-boot-and-spring-security). This sample provides an easy to understand seed project for users wishing to combine Java Spring Security API Server with a single page application front-end. The sample can run in two different modes:
- - The SPA and API Server trust one another, and share the same Auth0 application information. In other words, they both have the same ClientId and therefore share the same Audience in their JWT Tokens. Hence the JWT Token received upon successful authentication in the SPA application is also passed in the Authorization Bearer header of the AJAX requests to the API Server. The API Server accepts the audience as it is the same as its own.
- - The SPA application and API Server each have their own Auth0 Application on a shared Tenant (Account / Domain). In this situation, each has a different ClientId, and the Audience of the JWT Token generated for each application is different. The SPA application logs in and receives a JWT Token for authentication / authorization checks local to the SPA application. When making AJAX requests to the API Server, a delegation token is used instead - in effect, the SPA application swaps its own JWT Token for a JWT Token that is valid for requests to the API Server.
+- [Companion SPA Applications](https://github.com/auth0-samples/auth0-spring-security-api-client-samples): A sample application that works as a companion for the [Auth0 Spring Security API Sample](https://github.com/auth0-samples/auth0-spring-security-api-sample) and [Auth0 Spring Security API Resource Server Sample](#auth0-resource-server-sample-using-spring-boot-and-spring-security). This sample provides an easy to understand seed project for users wishing to combine Java Spring Security API Server with a single-page application front-end. The sample can run in two different modes:
+ - The SPA and API Server trust one another and share the same Auth0 application information. In other words, they both have the same ClientId and therefore share the same Audience in their JWT Tokens. Hence the JWT Token received upon successful authentication in the SPA application is also passed in the Authorization Bearer header of the AJAX requests to the API Server. The API Server accepts the audience as it is the same as its own.
+ - The SPA application and API Server each have their own Auth0 Application on a shared Tenant (Account / Domain). In this situation, each has a different ClientId, and the Audience of the JWT Token generated for each application is different. The SPA application logs in and receives a JWT Token for authentication / authorization checks, local to the SPA application. When making AJAX requests to the API Server, a delegation token is used instead - in effect, the SPA application swaps its own JWT Token for a JWT Token that is valid for requests to the API Server.
You can find details on how to setup and use this sample application at the _README_ of the [GitHub repository](https://github.com/auth0-samples/auth0-spring-security-api-client-samples/tree/master/auth0-spring-security-api-angular-client).
-## Using Auth0 with Spring Boot and Spring Security for Single Sign On (SSO)
+## Using Auth0 with Spring Boot and Spring Security for Single Sign-on (SSO)
-We have created a [sample application](https://github.com/auth0-samples/auth0-spring-security-mvc-sso-sample) that demonstrates using Auth0 with Spring Boot and Spring Security to create two traditional server-side MVC web apps that are configured for Single Sign On with one another. `app1.com` is the main _portal_ website and `app2.com` is a _partner_ website that depends on `app1.com` for SSO authentication. The sample offers also one more _portal_ website, `app3.com`, which is a Single Page Application written in Angular 1.x. This is optional and provided for those wishing to do SSO with a mix of Server side and Single Page Apps.
+We have created a [sample application](https://github.com/auth0-samples/auth0-spring-security-mvc-sso-sample) that demonstrates using Auth0 with Spring Boot and Spring Security to create two traditional server-side MVC web apps that are configured for SSO with one another. `app1.com` is the main _portal_ website and `app2.com` is a _partner_ website that depends on `app1.com` for Single Sign-on (SSO) authentication. The sample also offers one more _portal_ website, `app3.com`, which is a Single-Page Application written in Angular 1.x. This is optional and provided for those wishing to do SSO with a mix of Server side and Single-Page Apps.
-The aim of this solution is to provide a simple, no-frills sample, developers can follow to understand the orchestration required to achieve SSO using Auth0 using Java, without having to also cope with understanding additional libraries or frameworks.
+The aim of this solution is to provide a simple, no-frills sample that developers can follow to understand the orchestration required to achieve SSO using Auth0 using Java, without having to also cope with understanding additional libraries or frameworks.
You can find more details on how to setup and use this sample application [here](https://github.com/auth0-samples/auth0-spring-security-mvc-sso-sample).
## Auth0 Resource Server Sample using Spring Boot and Spring Security
-We have created a [sample application](https://github.com/auth0-samples/auth0-spring-security-api-resource-server-sample) that demonstrates using Auth0 with Spring Boot and Spring Security to create a secure Resource Server. This sample would be suitable for headless APIs and SPA (single page application) backend end server scenarios. It is specifically intended to demonstrate how to setup and read `scope` information from an Auth0 IDP JWT [Access Token](/tokens/access_token), and use this information to control authentication and authorization to secured endpoints.
+We have created a [sample application](https://github.com/auth0-samples/auth0-spring-security-api-resource-server-sample) that demonstrates using Auth0 with Spring Boot and Spring Security to create a secure Resource Server. This sample would be suitable for headless APIs and SPA (single-page application) backend end server scenarios. It is specifically intended to demonstrate how to setup and read `scope` information from an Auth0 IDP JWT [Access Token](/tokens/access_token) as well as how to use this information to control authentication and authorization to secured endpoints.
This sample application shows you how to:
- Configure and run Java based Spring API server with Auth0 and Spring Security.
diff --git a/articles/dev-lifecycle/child-tenants.md b/articles/dev-lifecycle/child-tenants.md
index 2ca30101f0..3c2bdba948 100644
--- a/articles/dev-lifecycle/child-tenants.md
+++ b/articles/dev-lifecycle/child-tenants.md
@@ -1,13 +1,22 @@
---
description: How to request child tenants for your Auth0 tenant
+topics:
+ - child-tenants
+ - dev-tools
+contentType: how-to
+useCase:
+ - support
+ - development
---
# Child Tenant Request Process
-This request process is for self-service customers requesting a development, test, or staging tenant that's linked to their paid production tenant. This tenant is called a **child tenant**.
+This request process is for Developer or Developer Pro customers requesting a development, test, or staging tenant that's linked to their paid production tenant. This tenant is called a **child tenant**.
-::: note
Free tenants do not include a child tenant.
+
+::: warning
+This policy does not apply if you have an Enterprise subscription. If you need to add child tenants to your subscription, contact your designated Technical Account Manager or our [Support](${env.DOMAIN_URL_SUPPORT}).
:::
## Child Tenant Policy
diff --git a/articles/dev-lifecycle/index.md b/articles/dev-lifecycle/index.md
index 6328251492..69cd2850f7 100644
--- a/articles/dev-lifecycle/index.md
+++ b/articles/dev-lifecycle/index.md
@@ -2,6 +2,12 @@
classes: topic-page
title: Development Lifecycle
description: Introduction to development lifecycle in Auth0.
+topics:
+ - dev-tools
+contentType:
+ - index
+ - how-to
+useCase: development
---
diff --git a/articles/dev-lifecycle/local-testing-and-development.md b/articles/dev-lifecycle/local-testing-and-development.md
index 9b8b37a1bc..128c09eb32 100644
--- a/articles/dev-lifecycle/local-testing-and-development.md
+++ b/articles/dev-lifecycle/local-testing-and-development.md
@@ -1,32 +1,45 @@
---
description: How to develop and test Auth0 applications.
+topics:
+ - dev-tools
+ - local-env
+contentType: how-to
+useCase: development
---
# Work with Auth0 Locally
In most cases, authenticating users through Auth0 requires an Internet connection. However, you can still develop and test apps that use Auth0 locally. In some cases, you might not need access to an Internet connection.
::: note
-Please see [Setting Up Multiple Environments](/dev-lifecycle/setting-up-env) for information on structuring your development, test, and production environments when using Auth0.
+See [Setting Up Multiple Environments](/dev-lifecycle/setting-up-env) for information on structuring your development, test, and production environments when using Auth0.
:::
-## Use JSON Web Tokens (JWT) with Client-Side Applications
+## Use JSON Web Tokens (JWT) with client-side applications
-Because [JSON Web Tokens (JWT)](/jwt) are stateless (that is, the app that consumes them cares only about its contents, not any of its previous states), this is one of the easiest scenarios to test locally.
+Because [JSON Web Tokens (JWT)](/tokens/concepts/jwts) are stateless (that is, the app that consumes them cares only about its contents, not any of its previous states), this is one of the easiest scenarios to test locally.
You can obtain JWTs for testing using any of the following methods:
-1. Create a test user for a database [connection](/identityproviders), and programatically log this user in. Essentially, you are using the recommended process for [calling an API using a highly-trusted application](/api-auth/grant/password). For detailed implementation instructions, see [Execute the Resource Owner Password Grant](/api-auth/tutorials/password-grant).
+1. Create a test user for a database [connection](/identityproviders), and programmatically log this user in. Essentially, you are using the recommended process for [calling an API using a highly-trusted application](/api-auth/grant/password). For detailed implementation instructions, see [Execute the Resource Owner Password Grant](/api-auth/tutorials/password-grant).
-2. Use a browser bot (such as Selenium) to play the role of a user, log in and retrieve a JWT. While this approach may take some effort to develop and maintain, it will allow you to test any [redirection rules](/rules/redirect) or [MFA prompts](/multifactor-authentication) that you have configured.
+2. Use a browser bot (such as Selenium) to play the role of a user, log in and retrieve a JWT. While this approach may take some effort to develop and maintain, it will allow you to test any [redirection rules](/rules/redirect) or [MFA prompts](/mfa) that you have configured.
-## Use Sessions with Server-Side Applications
+## Use sessions with server-side applications
Unless your server-side application allows the generation of artificial sessions for testing, you'll need a way to perform a login through Auth0 manually.
-For a high-level overview of how to do this, see [Calling APIs from Server-side Web Apps](/api-auth/grant/authorization-code). For detailed implementation instructions, see [Execute an Authorization Code Grant Flow](/api-auth/tutorials/authorization-code-grant).
+For a high-level overview of how to do this, see [Authorization Code Flow](/flows/concepts/auth-code). For detailed implementation instructions, see our tutorial, [Call API Using the Authorization Code Flow](/flows/guides/auth-code/call-api-auth-code).
-## Use Local Domains with Auth0
+## Use local domains with Auth0
-If you're developing your application locally, you can use `localhost` and other domains inaccessible by Auth0 (such as those on an intranet) as callback URLs.
+If you're developing your application locally, you can use `localhost` and other domains inaccessible by Auth0 (such as those on an intranet) as [callback URLs](/users/guides/redirect-users-after-login). For example, during development you could use `http://localhost:3000/callback` as the callback URL.
-Because Auth0's main identity protocol is [OpenID Connect](/protocols), Auth0 never needs to directly call your application's server. Instead, Auth0 redirects users to your application's endpoint(s) with required information contained in a query string or hash fragment.
+To set a callback URL, go to [Applications > Settings](${manage_url}/#/applications/${account.clientId}/settings) and add the URL to the **Allowed Callback URLs** list.
+
+Because Auth0's main identity protocol is OpenID Connect (OIDC), Auth0 never needs to directly call your application's server. Instead, Auth0 redirects users to your application's endpoint(s) with required information contained in a query string or hash fragment.
+
+## Divert emails for testing
+
+If you want to test your local application and do not want the emails (creation, validation, etc.) to be delivered to the actual email address of the users your application creates or validates, Auth0 recommends using a custom email provider. For example, a service like [Mailtrap](https://mailtrap.io/signin) or your own custom SMTP server implementation can apply whatever logic you require to trap the emails. This ensures that users do not receive emails but you can access them for validation and troubleshooting.
+
+<%= include('../_includes/_email-domain-blacklist') %>
diff --git a/articles/dev-lifecycle/setting-up-env.md b/articles/dev-lifecycle/setting-up-env.md
index 5a5e4bf92d..f3ec26e81b 100644
--- a/articles/dev-lifecycle/setting-up-env.md
+++ b/articles/dev-lifecycle/setting-up-env.md
@@ -1,41 +1,50 @@
---
description: Use multiple Auth0 tenants to manage various environments.
+topics:
+ - dev-tools
+ - local-env
+contentType: how-to
+useCase: development
---
# Set Up Multiple Environments
-__Development__, __Test__, __Q&A__ environments are easy to setup in Auth0. Simply create a new tenant for each to guarantee the maximum isolation between these environments. You can easily switch between tenants using the tenant chooser from the top right menu on the dashboard. You can also configure different administrators for each.
+__Development__, __staging__, and __production__ environments are easy to set up in Auth0. Create a new tenant for each environment to guarantee isolation between them. You can easily switch between tenants using the tenant chooser from the top right menu on the Dashboard. You can also configure different administrators for each.
::: warning
-Moving your tenant to a Development environment will impact [rate limits](https://auth0.com/docs/policies/rate-limits) for calls to the Authentication and Management API.
+Production [rate limits](/policies/rate-limits) only apply to tenants tagged as `Production`. Ensure your tenant's environment tag is set to `Production` before going live.
:::
-
-
-The example above uses a simple naming convention to distinguish each environment, you can name your multiple environments anyway you prefer. No need to use this naming convention, though it is the one recommended.
+You can name your multiple environments any way you prefer. For production environments, we strongly recommend using [custom domains](/custom-domains).
::: note
-If you have a subscription plan costing at least **$167 (USD) per month**, you can request a [child account](/dev-lifecycle/child-tenants) that is identical to your Production account for use in a development/staging/testing environment. This includes paid/upgraded features, as well as individual configuration options, such as Rules. Free accounts do *not* include a child account.
+If you have a subscription plan costing at least **$167 (USD) per month**, you can request a [child account](/dev-lifecycle/child-tenants) that is identical to your Production account in terms of paid/upgraded features for use in a development/staging/testing environment. Free accounts do *not* include a child account.
:::
## Set the Environment
For each new tenant created, you should specify its environment. You can assign environment tags to your tenants to differentiate between development, staging, and production environments.
-To assign an environment tag to a tenant, go to the [Auth0 Support Center > Tenants](${env.DOMAIN_URL_SUPPORT}/tenants/public). Locate your tenant and click the gear icon to bring up the **Settings** section.
+::: note
+If your tenant is mixed use, choose the higher environment. For example, a tenant used for both development and production should be set to `Production`.
+:::
+
+1. To assign an environment tag to a tenant, go to the [Auth0 Support Center > Tenants](${env.DOMAIN_URL_SUPPORT}/tenants/public). Locate your tenant, and click the gear icon to bring up the **Settings** section.

Next, select the **Assign Environment Tag** option. Use the form to identify your tenant's environment as either `Development`, `Staging`, or `Production`.
-If your tenant is mixed use, choose the higher environment. For example, a tenant used for both development and production should be set to `Production`.
-
After selecting the environment, click on **Save Changes**.

+::: note
+Environment Tags are not available in [Private Cloud deployments ](/private-cloud). All tenants in the same environment will have the same limits.
+:::
+
## Migration
-Through the [Management API v2](/api/management/v2), you can automate the migration of assets (rules, database connections, and so forth) between tenants.
+Through the [Management API v2](/api/management/v2), you can automate the migration of assets ([rules](/rules/current), database [connections](/connections), and so forth) between tenants.
For easier configuration management, save your configuration values in the [Dashboard](${manage_url}/#/rules), instead of hardcoding them into your __rules__ or __db connections__ scripts.
@@ -48,13 +57,27 @@ function(user, context, callback){
}
```
-This code however is not portable since this URL will likely change from development to production.
+This code, however, is not portable since this URL will likely change from development to production.
+
+The recommended way of working with code that you need to use/move from development to product is via [Rules](${manage_url}/#/rules) section. If you have not yet created a rule, you'll need to do so. (Otherwise, jump to step 4.)
+
+1. Click __Create Your First Rule__.
+
+
+
+2. Choose the __empty rule__ template.
-The recommended way is to navigate to the [Dashboard > Rules](${manage_url}/#/rules), scroll at the bottom of the page, set your configuration value (we will use `log_url` for the key name, and `https://someurl/log` for value), and click __Create__.
+
+
+3. Enter a name for your new rule, and click __Save__.
+
+
+
+4. Navigate back to [Auth0 Dashboard Rules](${manage_url}/#/rules), and scroll to the bottom of the page to set your configuration values (we will use `log_url` for the key name, and `https://someurl/log` for value), then click __Create__.

-Now you can write your rule as follows:
+5. Now, you can write your rule. Edit the rule you created, enter the following code in the code area, and click __Save__.
```js
function(user, context, callback){
@@ -63,12 +86,14 @@ function(user, context, callback){
}
```
-This code is portable and when you migrate to production you only need to change this setting, instead of searching your scripts.
+
+
+This code is portable, and when you migrate to production, you only need to change this setting instead of searching your scripts.
## AD/LDAP Connectors
-Since an AD/LDAP Connector is tied to a specific Connection within an Auth0 tenant, if you setup multiple Auth0 tenants, you will need to create an AD/LDAP Connection and setup an AD/LDAP Connector for each tenant that requires this form of authentication.
+If you use multiple Auth0 tenants with AD/LDAP, you will need to create an AD/LDAP Connection and set up an AD/LDAP Connector for each tenant. This is because each AD/LDAP Connector is tied to a specific Connection within an Auth0 tenant.
-Multiple AD/LDAP Connectors can point to the same AD or LDAP directory, but each AD/LDAP connector can only be used by one Connection within one Auth0 tenant.
+Multiple AD/LDAP Connectors can point to the same AD or LDAP directory, but each AD/LDAP Connector can only be used by one Connection within one Auth0 tenant.
-If you have multiple AD/LDAP directories against which users will authenticate (for example, to support different departments or customers, each with their own directory) you can setup multiple AD/LDAP Connectors within each Auth0 tenant.
+If you have multiple AD/LDAP directories against which users will authenticate (for example, to support different departments or customers, each with their own directory), you can set up multiple AD/LDAP Connectors within each Auth0 tenant.
diff --git a/articles/email/custom.md b/articles/email/custom.md
index 3c09eb4d1c..904c232284 100644
--- a/articles/email/custom.md
+++ b/articles/email/custom.md
@@ -1,29 +1,34 @@
---
description: The Auth0 APIs provide endpoints that allow you to completely manage email flow, and control when and how emails are sent.
toc: true
+topics:
+ - email
+contentType: concept
+useCase: customize-emails
---
# Custom Email Handling
The default email flow in Auth0 can address the requirements of most applications, but there may be instances where more flexibility is required. For example:
- * Localization
- * Custom **Redirect To** URLs based on the user or tenant
- * Different email templates per application or tenant
+* Localization
+* Custom **Redirect To** URLs based on the user or tenant
+* Different email templates per application or tenant
The Auth0 Management API provides endpoints that allow you to completely manage email flow, and control when and how emails are sent.
To begin, you will need to disable automatic emails by deselecting **Status** under the **Verification Email** and **Welcome Email** tabs on the [Email Templates](${manage_url}/#/emails) page of the Auth0 dashboard.
-
-
## Verification Email
A verification email should be sent to every user for which the `email_verified` property is `false`. Typically, these are users in database connections or users authenticating with Social Providers that do not validate email addresses upon new user registration.
-Using a [Rule](/rules), you can call your API when a user logs in for the first time with an email address that has not been verified. After calling your API, [add a flag](/rules/metadata-in-rules) to the user's profile metadata that indicates that the verification email has been sent:
+Using a [Rule](/rules), you can call your API when a user logs in for the first time with an email address that has not been verified. After calling your API, [add a flag](/users/concepts/overview-user-metadata) to the user's profile metadata that indicates that the verification email has been sent:
```js
function (user, context, callback) {
+
+ const request = require('request');
+
user.user_metadata = user.user_metadata || {};
if (user.email_verified || user.user_metadata.verification_email_sent) {
return callback(null, user, context);
@@ -34,7 +39,7 @@ function (user, context, callback) {
json: {
user: user,
context: context,
- secretToken: ";ojhsajk;h;Kh:Jh",
+ secretToken: configuration.MY_SECRET_TOKEN,
},
timeout: 5000
}, function(err, response, body){
@@ -61,12 +66,17 @@ A custom redirect is useful when you want to direct users to certain URLs based
The Auth0 Management API provides a [post_verification_email](/api/v2#!/Tickets/post_email_verification) endpoint that generates the verification link for each user. This endpoint allows you to specify the `resultUrl` to which users will be redirected after they have validated their email address by clicking the link in the verification email.
+We recommend whitelisting the url through the dashboard.
+
## Welcome Email
A welcome email is sent to users once they have verified their email address. This can be implemented using a rule which sends the email only if the user's email address has been verified and the email has not been sent previously.
```js
function (user, context, callback) {
+
+ const request = require('request');
+
if (!user.email_verified || user.welcome_email_sent) {
return callback(null, user, context);
}
@@ -84,7 +94,7 @@ function (user, context, callback) {
return callback(new Error(err));
// Email sent flag persisted in the user's profile.
- user.persistent.welcome_email_sent = true;
+ user.app_metadata.welcome_email_sent = true;
return callback(null, user, context);
});
}
diff --git a/articles/email/index.md b/articles/email/index.md
index bb18e59700..2f3fec2e0d 100644
--- a/articles/email/index.md
+++ b/articles/email/index.md
@@ -1,15 +1,24 @@
---
url: /email
description: Auth0 built-in email services.
+topics:
+ - email
+contentType:
+ - index
+ - reference
+ - how-to
+useCase: customize-emails
---
# Emails in Auth0
+An Auth0 [Database Connection](/connections/database) provides several emails as a part of its authentication flow, including verification emails, welcome emails, change password emails, breached password, and blocked account emails. The **Multi-factor Authentication Enrollment Email** can be sent to users in any connection.
+
::: warning
-Auth0's built-in email provider is not supported for use in a production environment and should be used for testing only.
+Auth0's built-in email provider is not supported for use in a production environment, should be used for testing only, and has several restrictions.
:::
-When you first create your application Auth0 provides a built-in email provider to send emails. This includes verification emails, welcome emails, change password emails, and blocked account emails. This is meant to be used for testing purposes only, and has several restrictions:
+Auth0's built-in email provider has these restrictions:
* You will not be able to use any of the email customization features. The content of the emails sent for testing will be restricted to format of the existing templates.
@@ -29,7 +38,7 @@ To remove these restrictions in your testing or to setup your production level e
After you have configured your own email service provider, the [Emails](${manage_url}/#/emails) dashboard will allow you to customize your emails beyond the existing templates.
::: note
-For users with the **Free Subscription** plan, email workflows and using the custom email provider features are available. However a paid subscription plan is required for email customizations. See the [subscription pricing page](https://auth0.com/pricing) for more details.
+For users with the **Free Subscription** plan, email workflows and using the custom email provider features are available. However, a paid subscription plan is required for email customizations. See the [subscription pricing page](https://auth0.com/pricing) for more details.
:::
For more information see [Customizing Your Emails](/email/templates).
diff --git a/articles/email/liquid-syntax.md b/articles/email/liquid-syntax.md
index 06ae3b12eb..205cd9025e 100644
--- a/articles/email/liquid-syntax.md
+++ b/articles/email/liquid-syntax.md
@@ -1,5 +1,12 @@
---
description: How to use Liquid syntax in your email templates.
+topics:
+ - email
+ - liquid
+contentType:
+ - how-to
+ - concept
+useCase: customize-emails
---
# Liquid Syntax in Email Templates
diff --git a/articles/email/providers.md b/articles/email/providers.md
index 3d25685ac1..659f40862b 100644
--- a/articles/email/providers.md
+++ b/articles/email/providers.md
@@ -1,185 +1,220 @@
---
-description: How to configure your own SMTP email provider.
+title: Use Your Own SMTP Email Provider
+description: Learn how to configure your own SMTP email provider, so you can more completely manage, monitor, and troubleshoot your email communications.
toc: true
+topics:
+ - email
+ - smtp
+ - email-providers
+contentType: how-to
+useCase: customize-emails
---
-# Use your own SMTP Email Provider
+# Use Your Own SMTP Email Provider
-Auth0 allows you to configure your own SMTP email provider. Auth0's built-in email infrastructure should be used for testing level emails only. By using your own provider you can more completely manage, monitor and troubleshoot your email communications.
+Auth0 allows you to configure your own SMTP email provider so you can more completely manage, monitor, and troubleshoot your email communications.
+
+::: note
+Auth0's built-in email infrastructure should be used for testing-level emails only.
+:::
Auth0 currently supports the following providers:
-* [Amazon SES](#configure-amazon-ses-for-sending-email)
-* [Mandrill](#configure-mandrill-for-sending-email)
-* [SendGrid](#configure-sendgrid-for-sending-email)
-* [SparkPost](#configure-sparkpost-for-sending-email)
-* [Custom SMTP](#configure-a-custom-smtp-server-for-sending-email)
+* [Amazon SES](#configure-amazon-ses)
+* [Mandrill](#configure-mandrill)
+* [SendGrid](#configure-sendgrid)
+* [SparkPost](#configure-sparkpost)
+* [Mailgun](#configure-mailgun)
+* [Other SMTP](#configure-a-custom-smtp-server) (e.g., Gmail, Yahoo)
-::: note
-You can only configure one email provider (Amazon SES, Sendgrid, and so on.) which will be used for all emails.
-:::
+You can only configure one email provider, which will be used for all emails.
+
+## Whitelist IP addresses
-## Configure Amazon SES for Sending Email
+To ensure that emails can be sent from Auth0 to your SMTP, you must open the right ports and allow inbound connections from specific IP addresses. To get the list of IPs, navigate to [Dashboard > Emails > Provider](${manage_url}/#/templates/provider).
-There are several steps to follow to configure Amazon SES for sending email. If you want to use the SES API, please follow this guide.
+## Configure Amazon SES
-You can use two types of credentials
+To use the Amazon SES API to send emails, you must complete several configuration steps. First, though, you need to decide which credentials you want to use:
-1. API Credentials
-2. SMTP Credentials (the secret is usually 44 characters long)
+* API Credentials
+* SMTP Credentials (the secret is usually 44 characters long)
-For more information about SES credentials, visit [Using Credentials With Amazon SES](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-credentials.html).
+For more info about SES credentials, see Amazon's [Using Credentials With Amazon SES](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-credentials.html).
-### Using API Credentials
+### Use API credentials
+
+1. Sign up for an [Amazon AWS](http://aws.amazon.com/ses/) account, or log in.
-1. Sign up for an [Amazon AWS](http://aws.amazon.com/ses/) account, or login.
2. [Verify your domain](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domains.html).
- 
3. [Verify email addresses](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-email-addresses.html)
4. [Request production access](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html?icmpid=docs_ses_console).
-5. [Get Your AWS Access Keys](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/get-aws-keys.html). Copy these keys. You will need to enter these values into Auth0 (see below).
- 
+5. [Get your AWS access keys](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/get-aws-keys.html). Copy these keys; you will need to enter these values into Auth0.
-6. [Attach a policy with the right permissions](http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html). Attach a policy with the `ses:SendRawEmail` and `ses:SendEmail` permissions, as in this example:
+6. [Attach a policy with the proper permissions](http://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage.html). Attach a policy with the `ses:SendRawEmail` and `ses:SendEmail` permissions, as in this example:
- 
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ses:SendRawEmail",
+ "ses:SendEmail"
+ ],
+ "Resource": "*"
+ }
+ ]
+}
+```
-7. Go to the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. Click **Use my own Email Provider** and click the **Amazon Web Services** logo.
+7. Navigate to Auth0 [Custom Email Providers](${manage_url}/#/emails/provider). Activate the **Use my own email provider** toggle, and click the **Amazon Web Services** logo.
-8. Enter your AWS `Access Key Id`, `Secret Access Key` and `Region` in the appropriate fields:
+ 
- 
+8. Provide a **From** email address, enter your AWS **Access Key Id** and **Secret Access Key**, select your **Region**, and click **Save**:
-9. Click **Save**.
+ 
-Now you can send a test email using the **SEND TEST EMAIL** button on the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. If you don't receive an email after a few minutes, please check your [dashboard logs](${manage_url}/#/logs) for any failures.
+You can now send a test email using the **Send Test Email** button. If you have configured everything correctly, you will receive a confirmation email. If you do not receive an email after a few minutes, please check your [Auth0 logs](${manage_url}/#/logs) for any failures.
-The [Amazon SES console](https://console.aws.amazon.com/ses) will now display all emails which have been sent to your users.
+The [Amazon SES console](https://console.aws.amazon.com/ses) will now display delivery insights for all emails that have been sent to your users.
-### Using SMTP Credentials
+### Use SMTP credentials
-1. Sign up for an [Amazon AWS](http://aws.amazon.com/ses/) account, or login.
-2. [Verify your domain](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domains.html).
+1. Sign up for an [Amazon AWS](http://aws.amazon.com/ses/) account, or log in.
- 
+2. [Verify your domain](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domains.html).
3. [Request production access](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html?icmpid=docs_ses_console).
-4. [Get Your SMTP Credentials](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html). Copy the security credentials. You will need to enter these values into Auth0.
+4. [Get your SMTP credentials](http://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html). Copy the security credentials; you will need to enter these values into Auth0.
+
+5. Navigate to Auth0 [Custom Email Providers](${manage_url}/#/emails/provider). Activate the **Use my own email provider** toggle, and click the **SMTP** logo.
+
+ 
+
+6. Provide a **From** email address, then enter your SMTP server **Host**, **Port**, **Username**, and **Password**, and click **Save**. You can use `email-smtp.us-east-1.amazonaws.com` (using the appropriate region rather than `us-east-1`) for **Host** and `587` for **Port**.
- 
+ 
-5. Go to the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. Click **Use my own Email Provider** and click the **SMTP** logo.
+You can now send a test email using the **Send Test Email** button. If you have configured everything correctly, you will receive a confirmation email. If you do not receive an email after a few minutes, please check your [Auth0 logs](${manage_url}/#/logs) for any failures.
-6. Enter your SMTP server `Host`, `Port`, `Username` and `Password` in the appropriate fields. You can use `email-smtp.us-east-1.amazonaws.com` (using the appropriate region instead of `us-east-1`) for `Host` and `587` for `Port`.
+The [Amazon SES console](https://console.aws.amazon.com/ses) will now display delivery insights for all emails that have been sent to your users.
- 
+## Configure Mandrill
-7. Click **Save**.
+1. Sign up for a [Mandrill](https://www.mandrill.com/signup/) account, or log in.
-Now you can send a test email using the **SEND TEST EMAIL** button on the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. If you don't receive an email after a few minutes, please check your [dashboard logs](${manage_url}/#/logs) for any failures.
+2. Navigate to Mandrill [Settings](https://mandrillapp.com/settings), and click **Add API key**. Copy this key value.
-The [Amazon SES console](https://console.aws.amazon.com/ses) will now display all emails which have been sent to your users.
+3. Navigate to Auth0 [Custom Email Providers](${manage_url}/#/emails/provider). Activate the **Use my own email provider** toggle, and click the **Mandrill** logo.
-## Configure Mandrill for Sending Email
+ 
-1. Sign up for a [Mandrill](https://www.mandrill.com/signup/) account, or login. Go to the [Settings page](https://mandrillapp.com/settings) and click **Add API key**. Save this key value.
+4. Provide a *From** email address, enter the Mandrill **API Key** you previously copied, and click **Save**:
- 
+ 
-2. Go to the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. Click **Use my own Email Provider** and click the **Mandrill** logo.
+You can now send a test email using the **Send Test Email** button. If you have configured everything correctly, you will receive a confirmation email. If you do not receive an email after a few minutes, please check your [Auth0 logs](${manage_url}/#/logs) for any failures.
-3. Enter your previously obtained Mandrill `API Key`:
+The Mandrill [Outbound Activity](https://mandrillapp.com/activity) page will now display delivery insights for all emails that have been sent to your users.
- 
+## Configure SendGrid
-Now you can send a test email using the **SEND TEST EMAIL** button on the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. If you don't receive an email after a few minutes, please check your [dashboard logs](${manage_url}/#/logs) for any failures.
+1. Sign up for a [SendGrid](https://sendgrid.com) account, or log in. (If you have a Microsoft Azure subscription, you can get a free account in the Azure Marketplace.)
-The [Outbound Activity](https://mandrillapp.com/activity) page in Mandrill will now display all emails which have been sent to your users, including the subject and the delivery status of each message.
+2. Navigate to SendGrid **Settings > API Keys**, and click **Create API Key**. Provide a name for your key, enable **Full Access** for **Mail Send** permissions, and click **Save**. Copy this key value.
-
+3. Navigate to Auth0 [Custom Email Providers](${manage_url}/#/emails/provider). Activate the **Use my own email provider** toggle, and click the **SendGrid** logo.
-## Configure SendGrid for Sending Email
+ 
-1. Sign up for a [SendGrid](https://sendgrid.com) account, or login. (If you have a Microsoft Azure subscription you can get a free account in the Azure Marketplace).
+4. Provide a **From** email address, enter the SendGrid **API Key** you previously copied, and click **Save**:
-2. Go to **Settings > API Keys** and click **Create API Key**.
-3. Provide a name for your key and enable **Full Access** for **Mail Send** permissions. Click **Save**.
+ 
- 
+You can now send a test email using the **Send Test Email** button. If you have configured everything correctly, you will receive a confirmation email. If you do not receive an email after a few minutes, please check your [Auth0 logs](${manage_url}/#/logs) for any failures.
-4. Copy the API key provided.
+The SendGrid [Email Activity](https://sendgrid.com/logs/index) page will now display delivery insights for all emails that have been sent to your users.
- 
+## Configure SparkPost
-5. Go to the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. Click **Use my own Email Provider** and click the **SendGrid** logo.
+1. Sign up for a [SparkPost](https://www.sparkpost.com/) account, or log in.
-6. Provide a **From** email and enter your previously obtained **SendGrid API Key**:
+2. Navigate to SparkPost [Sending Domains](https://app.sparkpost.com/account/sending-domains), and add your custom domain. SparkPost allows sending emails from only verified domains.
- 
+3. Navigate to SparkPost [Account API Keys](https://app.sparkpost.com/account/credentials), and click **New API key**. Save this key value and ensure it has `Transmissions: Read/Write` access. Copy this key value.
+4. Navigate to Auth0 [Custom Email Providers](${manage_url}/#/emails/provider). Activate the **Use my own email provider** toggle, and click the **SparkPost** logo.
-Now you can send a test email using the **SEND TEST EMAIL** button on the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. If you have configured everything correctly, you will receive a confirmation email:
+ 
+
+5. Provide a **From** email address, enter the SparkPost **API Key** you previously copied, select your **Region**, and click **Save**:
+
+ 
+
+::: warning
+If you are changing to the EU region in an account that was already configured for the US region, you must replace the **API Key** in Auth0 with a Sparkpost EU API Key.
+:::
-
+You can now send a test email using the **Send Test Email** button. If you have configured everything correctly, you will receive a confirmation email. If you do not receive an email after a few minutes, please check your [Auth0 logs](${manage_url}/#/logs) for any failures.
::: note
-If you do not receive an email after a few minutes, please check your [dashboard logs](${manage_url}/#/logs) for any failures.
+If you haven't registered a custom domain with SparkPost, you can send a maximum of five test emails from the `sparkpostbox.com` domain. For more info, see SparkPost's [Transmissions: The Sandox Domain](https://developers.sparkpost.com/api/transmissions.html#header-the-sandbox-domain).
:::
-The [Email Activity](https://sendgrid.com/logs/index) page in SendGrid will now display all emails which have been sent to your users and the delivery status of each message.
+The SparkPost [Message Events](https://app.sparkpost.com/reports/message-events) page will now display delivery insights for all emails that have been sent to your users.
-
+## Configure Mailgun
-## Configure SparkPost for Sending Email
+1. Sign up for a [Mailgun](https://mailgun.com) account, or log in.
-1. Sign up for a [SparkPost](https://www.sparkpost.com/) account, or login. Go to the [Account API Keys page](https://app.sparkpost.com/account/credentials) and click **New API key**. Save this key value. The key must have `Transmissions: Read/Write` access.
+2. Navigate to Mailgun **Sending > Domains**, and add your custom domain. Mailgun allows sending emails from only verified domains.
- 
+3. Navigate to Mailgun **Settings > API Keys**. Your API key was created when you signed up for your account; copy it from **Private API Key**.
-2. Go to the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. Click **Use my own Email Provider** and click the **SparkPost** logo.
+4. Navigate to Auth0 [Custom Email Providers](${manage_url}/#/emails/provider). Activate the **Use my own email provider** toggle, and click the **Mailgun** logo.
-3. Enter your previously obtained SparkPost `API Key`:
+ 
- 
+5. Provide a **From** email address, enter the **Domain** you previously added to Mailgun, enter the Mailgun **API Key** you previously copied, select your **Region**, and click **Save**:
-Now you can send a test email using the **SEND TEST EMAIL** button on the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. Note that SparkPost only allows sending emails from verified domains. To verify a custom domain go to the [Sending Domains page](https://app.sparkpost.com/account/sending-domains) and add your custom domain. Alternatively, you can send test emails from the `sparpostbox.com` domain, but this is limited to only five test emails. See the [relevant SparkPost docs](https://developers.sparkpost.com/api/transmissions.html#header-the-sandbox-domain) for details.
+ 
-If you don't receive an email after a few minutes, please check your [dashboard logs](${manage_url}/#/logs) for any failures.
+You can now send a test email using the **Send Test Email** button. If you have configured everything correctly, you will receive a confirmation email. If you do not receive an email after a few minutes, please check your [Auth0 logs](${manage_url}/#/logs) for any failures.
-The [Message Events](https://app.sparkpost.com/reports/message-events) page in SparkPost will now display all emails which have been sent to your users, including the delivery status of each message.
+The [Mailgun Dashboard](https://app.mailgun.com/app/dashboard) will now display delivery insights for all emails that have been sent to your users.
-
+## Configure a custom SMTP server
-## Configure a Custom SMTP Server for Sending Email
+When using your own SMTP server to send email, the server must:
-You can use your own SMTP server to send email. There are three requirements for the SMTP server:
+* support LOGIN [authentication](https://en.wikipedia.org/wiki/SMTP_Authentication).
+* support [TLS](https://en.wikipedia.org/wiki/STARTTLS) 1.0 or higher.
+* use a certificate signed by a public certificate authority (CA).
-* It must support LOGIN [authentication](https://en.wikipedia.org/wiki/SMTP_Authentication).
-* It must support [TLS](https://en.wikipedia.org/wiki/STARTTLS) 1.0 or higher.
-* It must use a certificate signed by a public certificate authority (CA).
+If your SMTP server meets these criteria, then:
-To be able to use your own SMTP server:
+1. Navigate to Auth0 [Custom Email Providers](${manage_url}/#/emails/provider). Activate the **Use my own email provider** toggle, and click the **SMTP** logo.
-1. Open the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard.
-2. Click on **Use my own Email Provider**.
-3. Click the **SMTP** logo.
-4. Enter your SMTP server `Host`, `Port`, `Username` and `Password` in the appropriate fields:
+ 
- 
+2. Provide a **From** email address, then enter your SMTP server **Host**, **Port**, **Username**, and **Password**, and click **Save**:
-5. Click **Save**.
+ 
::: note
-Common ports include 25 and 587. Please avoid using port 25 if you can, since many providers have limitations on this port.
+Common ports include 25 and 587. Please avoid using port 25 if you can because many providers have limitations on this port.
:::
-Now you can send a test email using the **SEND TEST EMAIL** button on the [Custom Email Provider](${manage_url}/#/emails/provider) page of the Auth0 dashboard. If you don't receive an email after a few minutes, please check your [dashboard logs](${manage_url}/#/logs) for any failures.
+You can now send a test email using the **Send Test Email** button. If you have configured everything correctly, you will receive a confirmation email. If you do not receive an email after a few minutes, please check your [Auth0 logs](${manage_url}/#/logs) for any failures.
::: panel Test services
-SMTP makes it easy to setup test services that allow you to test that your setup is working without spamming your users. For more information, see: [Set up a Test SMTP Provider](/email/testing) .
+SMTP makes it easy to set up test services that allow you to test that your setup is working without spamming your users. For more info, see [Set Up a Test SMTP Provider](/email/testing).
:::
## Keep reading
diff --git a/articles/email/spa-redirect.md b/articles/email/spa-redirect.md
index 3795331b9c..ff000c99f5 100644
--- a/articles/email/spa-redirect.md
+++ b/articles/email/spa-redirect.md
@@ -1,5 +1,10 @@
---
description: How to work around the limitation of single-page application email redirects.
+topics:
+ - email
+ - spa
+contentType: how-to
+useCase: customize-emails
---
# Single-Page App Email Redirect Issue
@@ -29,7 +34,7 @@ For example, with the above URL, the app will be routed to `/` instead of `/#/re
## Using a Query String Parameter
-To work around this limitation of SPA frameworks, it is recommended to use a server-side callback URL as the **redirect To** URL with a `route` parameter that preserves the SPA app route for the redirect. Once in this server-side URL, simply redirect to the SPA route saved in the `route` parameter along with rest of the query string.
+To work around this limitation of SPA frameworks, it is recommended to use a server-side callback URL as the **redirect To** URL with a `route` parameter that preserves the SPA app route for the redirect. Once in this server-side URL, simply redirect to the SPA route saved in the `route` parameter along with rest of the query string.
1. Add a server-side URL as the **redirect To** URL with a `route` parameter that records the SPA route for the redirect.
diff --git a/articles/email/templates.md b/articles/email/templates.md
index 93b41b4047..cc7a76a95c 100644
--- a/articles/email/templates.md
+++ b/articles/email/templates.md
@@ -1,40 +1,90 @@
---
description: The Emails section of the Auth0 dashboard allows you to customize your emails with Liquid templating syntax.
+topics:
+ - email
+contentType: how-to
+useCase: customize-emails
+toc: true
---
# Customizing Your Emails
::: warning
-You must setup your own email provider using a [third-party service](/email/providers) ([Amazon SES](https://aws.amazon.com/ses/), [Mandrill](https://www.mandrill.com/signup/) or [SendGrid](https://sendgrid.com/pricing)) or a [custom provider](/email/custom) to be able to customize your emails.
+You must set up your own email provider using a [third-party service](/email/providers) (such as Amazon SES, Mandrill, SendGrid, SparkPost, Mailgun, or a custom SMTP provider) to be able to customize your emails.
:::
-The [Emails](${manage_url}/#/emails) dashboard allows you to customize your emails, including templating with some user attributes [using Liquid syntax](#email-templates). This can include references to the context of the current application or user.
+Auth0 provides an [Emails](${manage_url}/#/emails) dashboard that allows you to customize your HTML-based emails, including templating with some contextual attributes [using Liquid syntax](/email/liquid-syntax). This can include references to the context of the current application or user.

::: note
-Only one template can be used for each template type (for example, only one template for change password emails).
+Only one template can be used for each template type (for example, only one template for verify emails).
:::
-## Configuring *From*, *Subject*, *Redirect To*, and *URL Lifetime*
+At this time, Auth0 does not support plaintext/text-based emails.
-For each type of email, you can customize the **From Address**, the **Subject**, the **Redirect To** and the **URL Lifetime**.
+## Configuring email templates
-### From Address
+You can customize the **From Address**, the **Subject**, and the **Message** body for each email template. You can use [Liquid Syntax](/email/liquid-syntax) to dynamically generate content, with access to a number of contextual variables that will be replaced with the relevant values when rendering the email messages.
+
+### Common variables
+
+You can access the following common variables when using Liquid Syntax in the **From Address**, **Subject** and **Message** fields:
+
+* The `application` object, with access to the standard client properties like
+ * `application.name`
+ * `application.clientID`
+* `connection.name` (except in the **Multi-factor Enrollment Email**)
+* The `user` object, with access to the following properties:
+ * `user.email`
+ * `user.email_verified`
+ * `user.picture`
+ * `user.nickname`
+ * `user.given_name`
+ * `user.family_name`
+ * `user.name`
+ * `user.app_metadata` - stores information (such as a user's support plan, security roles, or access control groups) that can impact a user's core functionality, such as how an application functions or what the user can access.
+ * `user.user_metadata` - stores user attributes (such as user preferences) that do not impact a user's core functionality.
+* Tenant-related information (defined in the [Tenant Settings](${manage_url}/#/tenant)):
+ * `tenant` - the raw tenant name
+ * `friendly_name`
+ * `support_email`
+ * `support_url`
+
+Variables are referenced using the `{{ variable_name }}` syntax in Liquid. E.g.:
+
+```text
+Hello {{ user.name }}. Welcome to {{ application.name }} from {{ friendly_name }}.
+```
+Note that the attributes available for the `user` object will depend on the type of connection being used.
+
+::: note
+Individual email templates define additional variables that are appropriate for the specific template. Be sure to check out the [individual templates descriptions](#individual-templates-descriptions) below.
+:::
+
+For those emails where the user needs to follow a link to take action, you can also configure the **URL Lifetime** and **Redirect To** URL destination after the action is completed. Liquid Syntax is also supported in the **Redirect To** URL field, but only three variables are supported:
+
+* `application.name`
+* `application.clientID`
+* `application.callback_domain`
+
+See [Configuring the Redirect To URL](#configuring-the-redirect-to-url) for more details.
+
+### Configuring the From Address
Users will see the sender's address in the **From Address** field when receiving an email from Auth0. If you do not configure a **From Address** for your emails your emails will be sent from the email address of the first owner of your Auth0 account.
::: note
-For security purposes, you may not send customized emails from any `@auth0.com` address. If you are a PSaaS Appliance user, you may configure a similar domain blacklist.
+For security purposes, you may not send customized emails from any `@auth0.com` address. If you are a Private Cloud user, you may configure a similar domain blacklist.
:::
-The **From Address** field supports the following macros:
+The **From Address** field supports all the [common variables](#common-variables) for templates, but these are the most commonly used:
-* `{application.name}`
-* `{connection.name}`
+* `application.name`
+* `friendly_name` (for the tenant's defined friendly name)
-You can use these macros to set the display name of the **From Address** to something that relates to the application for which the user signed up. For example, the field could display `{application.name} `, as opposed to simply ``.
+You can use these variables to set the display name of the **From Address** to something that relates to the application for which the user signed up. For example, the field could display `{{ application.name }} `, as opposed to simply ``.
You must add the [Sender Policy Framework (SPF)](http://en.wikipedia.org/wiki/Sender_Policy_Framework) and [DomainKeys Identified Mail (DKIM)](http://en.wikipedia.org/wiki/DKIM) DNS records to your domain's zone file to allow Auth0 to send digitally-signed emails on your behalf. Without these records, the emails may end up in your users' junkmail folders. Additionally, your users may see the following as the **From Address**:
@@ -44,7 +94,13 @@ MyApp support@mail128-21.atl41.mandrillapp.com on behalf of MyApp support@fabrik
#### SPF Configuration
-You can configure the SPF by adding a TXT record to your domain's zone file. You should set the host name to `@`, or leave it empty, depending on the provider.
+You can configure the SPF by adding a TXT record to your domain's zone file. You should set the host name to `@`, or leave it empty, depending on the provider. The value of the record should look something like the following.
+
+```text
+"v=spf1 include:spf.mandrillapp.com -all"
+```
+
+If you already have an SPF record you can simply add `include:spf.mandrillapp.com` to the existing record.
#### DKIM Configuration
@@ -60,74 +116,78 @@ and the value to:
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrLHiExVd55zd/IQ/J/mRwSRMAocV/hMB3jXwaHH36d9NaVynQFYV8NaWi69c1veUtRzGt7yAioXqLj7Z4TeEUoOLgrKsn8YnckGs9i3B3tVFB+Ch/4mPhXWiNfNdynHWBcPcbJ8kjEQ2U8y78dHZj1YeRXXVvWob2OaKynO8/lQIDAQAB;
```
-### Subject
+### Configuring the Subject
-You can use the following macros with the **Subject** field:
+The **Subject** field supports all the [common variables](#common-variables) for templates, including:
-* `{application.name}`
-* `{connection.name}`
-* `{user.email}`
+* `application.name`
+* `user.email` (and other properties of the `user` object)
If the **Subject** field is empty, Auth0 will auto-populate this text depending on what type of email you are sending. For example, one subject line might be "*Verify your email.*"
-### Redirect To URL
+### Configuring the URL Lifetime
+
+The **Verification Email**, **Change Password** and **Blocked Account Email** contain links which allow users to verify their email address when signing up, confirm their password change, or unblock a blocked account respectively.
-You can redirect users to a specific page on the **Allowed Callback URL** using the following:
+You can modify the lifetime of this link for security purposes. By default, the lifetime is 432,000 seconds (five days).
+
+If users click on an expired link and a **Redirect To** URL is configured, they will be redirected to the configured **Redirect To** URL. The following text will be appended to the query string:
```text
-{application.callback_domain}/result_page
+http://myapplication.com/my_page/?email=john%contoso.com&message=Access%20expired.&success=false
```
-If your application has multiple **Allowed Callback URLs** configured, Auth0 will use the first URL listed.
+### Configuring the Redirect To URL
-#### Dynamic Redirect To URLs
+The **Redirect To** URL is an optional destination to redirect the user to after the relevant action (verify account, reset password, unblock account) was performed.
-You can set up a different Redirect To URLs based on your Client ID. For example:
+::: panel Redirect URLs
+With the Classic Experience, you can provide a URL to which users are redirected after they reset their password. Auth0 sends a success indicator and a message to the URL.
-```text
-{% if application.clientID == '${account.clientId}' %} http://jwt.io {% else %} http://auth0.com {% endif %}
-```
-
-::: note
-For some single-page apps, the redirect to url can sometimes contain a hash that may be removed. This results in the **redirect To** url not working as expected. For more information, see: [Single-Page App Email Redirect Issue](/email/spa-redirect).
+With the New Experience, Auth0 redirects users to the [default log in route](/universal-login/default-login-url) when the user succeeds in resetting the password. If not, Auth0 handles the errors as part of the Universal Login flow and ignores the redirect URL provided in the email template.
:::
-### URL Lifetime
+**Only the following three variables** are available on the **Redirect To** URL:
-The **Verification Email** and **Change Password Confirmation Email** contain links which allow users to verify their email address when signing up, or confirm their password change, respectively.
+* `application.name` (or its synonym `client.name`)
+* `application.clientID`
+* `application.callback_domain` (or its synonym `client.callback_domain`)
+
+The `application.callback_domain` variable will contain the origin of the **first** URL listed in the application's **Allowed Callback URL** list. This lets you redirect users to a path of the application that triggered the action by using a syntax like this:
-You can modify the lifetime of this link for security purposes. By default, the lifetime is 432,000 seconds (five days).
+```text
+{{ application.callback_domain }}/result_page
+```
-If users click on an expired link and a **Redirect To** URL is configured, they will be redirected to the configured **Redirect To** URL. The following text will be appended to the query string:
+Note that while the variable is called `callback_domain`, it is really an *origin*, so it includes the protocol in addition to the domain, e.g. `https://myapp.com`.
+
+If your application has multiple **Allowed Callback URLs** configured, Auth0 will use the first URL listed. You can also provide a default origin using Liquid syntax:
```text
-http://myapplication.com/my_page/?email=john%contoso.com&message=Access%20expired.&success=false
+{{ application.callback_domain | default: "https://my-default-domain.com" }}/result_page
```
-## Email Templates
+#### Dynamic Redirect To URLs
-### Multilingual Email Templates
+You can set up a different Redirect To URLs based on your application name. For example:
-User attributes are available from the **Verification Email**, **Welcome Email**, **Change Password Confirmation Email** and **Blocked Account Email** templates.
+```text
+{% if application.name == 'JWT.io' %} https://jwt.io {% else %} https://auth0.com {% endif %}
+```
-The available attributes vary depending on the syntax used.
+Because the application name is encoded for security, you should always use an encoded value (especially if your application name contains a character that changes once encoded). For example, you'll want to use `My%20App` instead of `My App`.
+
+::: note
+For some single-page apps, the redirect to url can sometimes contain a hash that may be removed. This results in the **redirect To** url not working as expected. For more information, see: [Single-Page App Email Redirect Issue](/email/spa-redirect).
+:::
-#### HTML + Liquid syntax
-Liquid syntax is the currently supported templating syntax to use when accessing user attributes in your email templates. Here are the attributes available to you:
+### Configuring the Message Body
-* `email`
-* `email_verified`
-* `picture`
-* `name`
-* `nickname`
-* `given_name`
-* `family_name`
-* `app_metadata` - stores information (such as a user's support plan, security roles, or access control groups) that can impact a user's core functionality, such as how an application functions or what the user can access.
-* `user_metadata` - stores user attributes (such as user preferences) that do not impact a user's core functionality.
+Message bodies have HTML content, and Liquid syntax is the currently supported templating syntax to use. You can use all the [common variables](#common-variables) plus variables defined in each [individual template](#individual-templates-descriptions).
-[Learn more about `app_metadata` and `user_metadata`](/metadata)
+#### Multilingual Email Templates
-For example, you can refer to attributes in the template to control flow as follows:
+You can use Liquid syntax along with properties from the user object to alter the content based on the user preferred language. For example:
```text
{% if user.user_metadata.lang == 'es' %}
@@ -149,72 +209,73 @@ To assist your template development, we've added a custom `{% debug %}` liquid t
Use of Markdown in email templates has been deprecated, so you will no longer be able to add new Markdown formatting. If you have an existing template in Markdown, you will be able to toggle from Markdown to Liquid, but changing this setting will result in you losing any existing Markdown, as well as the ability to use Markdown.
:::
-The use of Markdown in email templating has been **deprecated**, and is only available for templates which were already using Markdown as the templating syntax. The available attributes for Markdown syntax are:
-
-* `email`
-* `email_verified`
-* `picture`
-* `name`
-* `nickname`
-* `given_name`
-* `family_name`
+The use of Markdown in email templating has been **deprecated**, and is only available for templates which were already using Markdown as the templating syntax.
+The Markdown syntax uses a `@@variable@@` format for variable substitution. The available variables are similar to those mentioned above for Liquid syntax.
-For example, you can refer to attributes in the template as follows:
+For example, you can refer to a user in the template as follows:
```text
Hello @@user.given_name@@ @@user.family_name@@
```
-### Verification Email
+## Individual Templates Descriptions
-When users sign-up or login for the first time, they will be sent a verification email. Clicking on the verification link in the email sets the 'email verified' property of their user profile to `true`.
+### Verification Email (Using Link)
-The following macros are available in the **Verification Email** template:
+If you turn on the **Verification Email**, users who sign up on a database connection will receive a message asking to confirm their email address by clicking on a URL included in the message.
-* `{application.name}`
-* `{connection.name}`
-* `{user.email}`
+In addition to the [common variables](#common-variables) available for all email templates, the **Verification Email** provides the `url` variable that refers to the URL that the user will have to click. You will use it in the **Message** field to create a link that the user can follow, as in this example:
-If you configure a **Redirect To** URL, the user will be directed to this URL after clicking the verification link. The following will be appended to the query string:
-
-```text
-http://myapplication.com/my_page/
- ?email=john%40contoso.com
- &message=Your%20email%20was%20verified.%20You%20can%20continue%20using%20the%20application.
- &success=true
+```html
+Confirm my account
```
+#### Redirect To Results for the Verification Email Template
-### Welcome Email
+You can [configure a **Redirect To** URL](#configuring-redirect-to) to send the users to after the email verification action was attempted. By default, Auth0 includes the following parameters:
-Once a user verifies their email address, they will receive a **Welcome Email**. If you turn off the **Verification Email** feature, the **Welcome Email** will be sent to the user when they sign-up (or login for the first time).
+* `success` with value `true` or `false` indicating whether the email verification was successful
+* `message` with an additional description of the outcome. Some possible values are:
+ * `Your email was verified. You can continue using the application.` (with `success=true`)
+ * `This URL can be used only once` (with `success=false`)
+ * `Access expired.` (with `success=false`)
+ * `User account does not exist or verification code is invalid.` (with `success=false`)
+ * `This account is already verified.` (with `success=false`)
+* `email` if `Include Email In Redirect` is enabled in the template. By default, `email` is not included
-The following macros are available in the **Welcome Email** template:
+The target URL handler should be prepared to gracefully handle other possible messages as well.
-* `{application.name}`
-* `{connection.name}`
-* `{user.email}`
+### Verification Email (Using Code)
-### Change Password Confirmation Email
+Azure AD and ADFS connections support an [email verification flow](/connections/azuread-email-verification#email-verification-flow-for-azure-ad/adfs- connections) using a one-time-use code. If you enable this feature, users will be prompted to enter the code before continuing the authentication flow.
-If a user requests a password change, they will receive a **Change Password Confirmation Email**. Until the user clicks the verification link contained in the email, the password will remain unchanged.
-If a user requests a password change, this email will be sent. The password will not be changed until the user follows the verification link in the email. @@url@@ (or {{ url }} if you are using the HTML + Liquid syntax) is a placeholder for the verification link.
+### Welcome Email
-The following macros are available in the **Change Password Confirmation** email template:
+Once a user verifies their email address, they will receive a **Welcome Email**. If you turn off the **Verification Email** feature, the **Welcome Email** will be sent to the user when they sign-up (or login for the first time).
-* `{application.name}`
-* `{connection.name}`
-* `{user.email}`
+### Change Password Email
-This email template has a [**Redirect To** URL field](#redirect-to-url), which contains the URL the user will be directed to URL after clicking the verification link. The following will be appended to the query string:
+If a user requests a password change, they will receive a **Change Password** that contains a URL link. When the user clicks on the link, a [Password Reset page](/universal-login/password-reset) will be presented to enter the new password.
-```text
-http://myapplication.com/my_page/
- ?success=true
- &message=You%20can%20now%20login%20to%20the%20application%20with%20the%20new%20password.
+In addition to the [common variables](#common-variables) available for all email templates, the **Change Password** has the `url` variable that refers to the URL that the user will have to click. You will use it in the **Message** field to create a link that the user can follow, as in this example:
+
+```html
+Click here to change your password
```
-This template also has a **URL Lifetime** field which is the lifetime of the URL in seconds. The default is 432000 seconds (5 days).
+#### Redirect To Results for the Change Password Template
+
+You can [configure a **Redirect To** URL](#configuring-redirect-to) to send the users to after the password change action was attempted. By default, Auth0 includes the following parameters:
+
+* `success` with value `true` or `false` indicating whether the password change was successful
+* `message` with an additional description of the outcome. Some possible values are:
+ * `You can now login to the application with the new password.` (with `success=true`)
+ * `This URL can be used only once` (with `success=false`)
+ * `Access expired.` (with `success=false`)
+ * `The operation cannot be completed. Please try again.` (with `success=false`)
+* `email` if `Include Email In Redirect` is enabled in the template. By default, `email` is not included
+
+The target URL handler should be prepared to gracefully handle other possible messages as well.
### Blocked Account Email
@@ -222,21 +283,88 @@ If a user attempts to login ten or more times unsuccessfully from the same IP ad
If the user successfully logs in before they exhaust their ten allowed attempts, the counter is reset.
-The following macros are available in the **Blocked Account Email** template:
+In addition to the [common variables](#common-variables) available for all email templates, the following ones are available in the **Blocked Account Email** template:
* `user.source_ip`
* `user.city`
* `user.country`
-* `application.name`
-* `connection.name`
-### Password Breach Alert
+This template also provides the `url` variable that should be used to create the link that the user needs to follow. E.g.:
+
+```html
+Click here to unblock your account
+```
+
+#### Redirect To Results for the Blocked Account Email Template
+
+You can [configure a **Redirect To** URL](#configuring-redirect-to) to send the users to after the account unblocking action was attempted. When redirecting, Auth0 will include the following parameters:
+
+* `email` indicating the email of the user
+* `success` with value `true` or `false` indicating whether the account unblocking was successful
+* `message` with an additional description of the outcome. Some possible values are:
+ * `Your account has been unblocked.` (with `success=true`)
+ * `This URL can be used only once` (with `success=false`)
+ * `Access expired.` (with `success=false`)
+
+The target URL handler should be prepared to gracefully handle other possible messages as well.
+
+### Password Breach Alert Email
This email type is sent whenever Auth0 detects that the user is trying to access the application using a password that has been leaked by a third party. These emails are only set after enabling **Breached Password Detection** in the [Anomaly Detection](${manage_url}/#/anomaly) section of the dashboard.
-The following macros are available in the **Password Breach Alert** template:
+Learn more about [Breached Password Detection](/anomaly-detection#breached-password-detection)
+
+### Multi-factor Authentication Enrollment Email
+
+This email will be generated when an multi-factor authentication enrollment invitation is sent. The message will contain a link that, when visited, will show the MFA enrollment experience.
+
+Besides the [common variables](#common-variables) available for all email templates, the `link` variable is available in this email type, containing the URL that you will use to construct the link for this action, as in this example:
+
+```html
+Enroll your MFA device
+```
-* `{application.name}`
-* `{connection.name}`
+Do note that, unlike other email templates, the correct variable name is `link` and not `url`. Also, the `connection.name` variable is not available on this email template type.
+
+### Verification Code for Email MFA
+
+This email will be generated when you use email as a MFA method and request a verification code to be sent.
+
+In addition to the [common variables](#common-variables) available, the template provides a `code` variable to render the code used for MFA verification. E.g.:
+
+```html
+
Your code is: {{ code }}
+```
+
+### Passwordless Email
+
+Unlike the previous email templates types, this email template is not configured from the Email Templates section. Instead, it's part of the [settings for the Email Passwordless Connection](${manage_url}/#/connections/passwordless).
+
+The Passwordless Email is sent when a passwordless access is requested, either by code (the user receives a code that types in the application) or by a link (the user clicks on a link and is taken directly to the application).
+
+You can use all the [common variables](#common-variables) available in all templates, plus the following variables defined specifically for the **Passwordless Email** template:
+
+* `send`, which will contain a value of `link`, `link_ios`, `link_android` or `code` depending on the type of passwordless email requested.
+* `code` with the one-time-use code to access the application
+* `link` with the link that can be clicked by the user to gain access to the application (only for link-type passwordless emails)
+* `request_language` will have the language code of the user request, if available
+* `operation`, which will be `change_email` if this is a passwordless email change operation.
+
+The default template uses the above variables to do something like this:
+
+```html
+
+{% if operation == 'change_email' %}
+
Your email address has been updated.
+{% else %}
+
+ {% if send == 'link' or send == 'link_ios' or send == 'link_android' %}
+
Click and confirm that you want to sign in to {{ application.name }}. This link will expire in five minutes.
+ {% endif %}
+{% endif %}
+```
-[Learn more about Breached Password Detection](/anomaly-detection#breached-password-detection)
+Note that in the Passwordless Email template only the `email` property of the `user` object is available.
diff --git a/articles/email/testing.md b/articles/email/testing.md
index 7644627193..827791ceba 100644
--- a/articles/email/testing.md
+++ b/articles/email/testing.md
@@ -1,5 +1,10 @@
---
description: Auth0 recommends you setup a fake SMTP server while in development or testing.
+topics:
+ - email
+ - smtp
+contentType: how-to
+useCase: customize-emails
---
# Set Up a Test SMTP Provider
@@ -16,6 +21,8 @@ You can either:
Once you have either your own SMTP server set up or a test service available, you can provide its credentials the way you typically would for a [custom email provider](/email/providers#configure-a-custom-smtp-server-for-sending-email).
+<%= include('../_includes/_email-domain-blacklist') %>
+
## Resources to Consider
::: next-steps
diff --git a/articles/errors/dbconnections/self_change_password.md b/articles/errors/dbconnections/self_change_password.md
deleted file mode 100644
index 7f83c2fcfd..0000000000
--- a/articles/errors/dbconnections/self_change_password.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-description: Error messages for the self change password API.
-public: false
----
-# Self Change Password Errors
-
-Below you will find the errors codes and possible solutions to various errors that can occur with the self change password api.
-
-## Error Format
-
-Error messages are returned in the standard format:
-
-```json
-{
- "error": "error_code",
- "error_description": "the description of the error.",
- "error_uri": "https://auth0.com/docs/errors/dbconnections/self_change_password"
-}
-```
-
-
-## Error Codes
-
-### `invalid_request`
-
-This error results when you supply invalid parameters. Error messages will describe the issue such as a required parameter or invalid format.
-
-
-### `invalid_user_password`
-
-This error results from a bad `username`/`email` and `old_password` combination being sent. Retry the request with the correct username and `old_password`.
-
-
-### `change_password_error`
-
-This error results from various conditions with the underlying identity provider. Generally, this happens when you are using a custom database and have not implemented the change password script.
diff --git a/articles/errors/deprecation-errors.md b/articles/errors/deprecation-errors.md
index 95ab54074c..f3b68bb35f 100644
--- a/articles/errors/deprecation-errors.md
+++ b/articles/errors/deprecation-errors.md
@@ -2,6 +2,14 @@
title: Deprecation Error Reference
description: A listing of errors and descriptions relating to deprecations.
toc: true
+topics:
+ - errors
+ - deprecation
+contentType:
+ - reference
+ - concept
+ - how-to
+useCase: error-management
---
# Deprecation Error Reference
@@ -9,11 +17,11 @@ When Auth0 features are deprecated, there may be errors or notices in the tenant
## How to search logs for deprecation warnings
-There are two different ways to search for warning messages showing usage of deprecated features: The Dashboard or the Management API. Note that in either case, the [log retention period](/logs#how-long-is-log-file-data-available-) is governed by the subscription level of your account.
+There are two different ways to search for warning messages showing usage of deprecated features: The Dashboard or the Management API. Note that in either case, the [log retention period](/logs/references/log-data-retention) is governed by the subscription level of your account.
### Search logs via the Dashboard
-If your application uses a deprecated feature, a Deprecation Notice message will show up in the Logs section of the [Dashboard](/${manage_url}).
+If your application uses a deprecated feature, a Deprecation Notice message will show up in the Logs section of the [Dashboard](${manage_url}/#/).
::: note
In order to not overwhelm the logs with repetitive messages, deprecation notes will only be shown once per hour (the first time it occurs within that hour) rather than for each authentication transaction involving the deprecated feature.
@@ -39,7 +47,7 @@ Customers can also use the Management API to search through logs for such messag
To check your logs using the Management API, go to the [Management API](/api/management/v2).
-If you have not already done so, [get and set up your API token](/api/management/v2/tokens#get-a-token-manually) in the API explorer.
+If you have not already done so, [get and get an API token](/api/management/v2/tokens).

@@ -56,7 +64,7 @@ Click on the **TRY** button. If successful, you should see a screen similar to t
* The results will match one of the messages + descriptions below.
* The **Client ID** field in the results will indicate which application (client) on your tenant is using the deprecated feature.
-## Deprecation Messages
+## Deprecation Log Messages
### up-idp-initiated
@@ -66,11 +74,10 @@ Click on the **TRY** button. If successful, you should see a screen similar to t
| Cause | Resolution |
| --- | --- |
-| You are using a legacy version of embedded Lock or Auth0.js SDK. | [Migrate to Universal Login](/guides/login/migration-embedded-universal) if possible or [upgrade to Lock v11 / Auth0.js v9](/migrations#introducing-lock-v11-and-auth0-js-v9) (Reference guide for [Lock v11](/libraries/lock/v11) and for [Auth0.js v9](/libraries/auth0js/v9)). |
-| Calling /login endpoint directly. | Migrate to use a form of the [/authorize endpoint](/api/authentication?http#login) as the start of authentication transactions. |
-| Users bookmarking the login URL and trying to initiate login from that bookmarked link at a later time. | Educate users to bookmark instead the place in your app to which they want to return (such as the home page). Depending on your design choices, and if there's no valid session for the user in the app, the app will either start the authorization process or show a login button. |
-| Users hitting the back button in the middle of a login transaction. | Educate users to start the login transaction again, starting from the initial login button/link, rather than using the back or forward button. |
+| You are using a legacy version of embedded Lock or Auth0.js SDK. | Migrate away from the deprecated library versions as soon as possible. |
| Calling the /usernamepassword/login endpoint directly. | Use the Lock or Auth0.js libraries instead. |
+| Automatic monitoring tools making requests to login page | If you have an automatic monitoring tool making requests to the login page, the tool will likely not preserve state correctly and will cause the Legacy Lock API error to occur in your logs. Use of the tool should either be discontinued, or accounted for when considering causes of the log notices. |
+| Coding errors in a customized [Universal Login Page](/universal-login) | Make sure the `state` and `_csrf` fields are passed to Lock or Auth0.js in your customized login page. They are by default included in the `config.internalOptions` object, but if this is removed during customization, the error occurs. |
### ssodata
@@ -81,3 +88,7 @@ Click on the **TRY** button. If successful, you should see a screen similar to t
| Cause | Resolution |
| --- | --- |
| Either calling the /ssodata directly or using old versions of embedded Lock or Auth0.js SDK to call a function which called the /ssodata endpoint. | [Migrate to Universal Login](/guides/login/migration-embedded-universal) or [migrate to Lock v11 or Auth0.js v9](/migrations#introducing-lock-v11-and-auth0-js-v9). |
+
+## Legacy Lock API troubleshooting
+
+Tenant log entries regarding the Legacy Lock API may include the referrer and information about the SDK used. This information can be used to see if any of your applications use outdated libraries.
diff --git a/articles/errors/libraries/auth0-js/invalid-token.md b/articles/errors/libraries/auth0-js/invalid-token.md
deleted file mode 100644
index 324b61a753..0000000000
--- a/articles/errors/libraries/auth0-js/invalid-token.md
+++ /dev/null
@@ -1,39 +0,0 @@
----
-public: true
----
-
-# Errors with code 'invalid_token'
-
-## Parsing an HS256-Signed ID Token Without an Access Token
-
-**Error Message**: The ID Token cannot be validated because it was signed using the HS256 algorithm and public applications (such as a browser) can’t store secrets. Please read the associated doc for ways to fix this.
-
-### Why this error occurred
-
-Beginning with **auth0.js version 9** and **Lock version 11**, when ID Tokens are signed with HS256, they are discarded and a call to **/userinfo** is made to retrieve user information.
-
-Calling **/userinfo** requires an Access Token. If you don't ask for an Access Token when authenticating, you will receive the following error:
-
-```
-The id_token cannot be validated because it was signed with the HS256 algorithm
-and public applications (like a browser) can’t store secrets.
-Please read the associated doc for possible ways to fix this.
-```
-
-### Ways to fix this error
-
-There are two ways to fix the error:
-
-1. **(RECOMMENDED)** Change the application signature algorithm to RS256 instead of HS256.
-2. Change the value of your **responseType** parameter to **token id_token** (instead of the default), so that you receive an Access Token in the response.
-
-To change the application signature algorithm to RS256 instead of HS256:
-
- 1. Go to [Dashboard > Applications]({$manage_url}/#/applications)
- 1. Select your application
- 1. Scroll to the bottom of the **Settings** tab, and click **Show Advanced Settings**
- 1. Open up the **OAuth** tab. Change the value of **JsonWebToken Signature Algorithm** to **RS256**
- 1. Scroll to the bottom of the page and click **Save Changes**
-
- If you proceed with this option and you are using the ID Token to call your APIs, be sure to change your server code so that it validates tokens using the RS256 algorithm instead of HS256. Note that using ID Tokens to call APIs [is not recommended](/api-auth/why-use-access-tokens-to-secure-apis).
-
diff --git a/articles/errors/managment-v2/placeholder.md b/articles/errors/managment-v2/placeholder.md
deleted file mode 100644
index 87f2df24fb..0000000000
--- a/articles/errors/managment-v2/placeholder.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-public: false
----
-
-# Management API Errors
\ No newline at end of file
diff --git a/articles/errors/oauth/placeholder.md b/articles/errors/oauth/placeholder.md
deleted file mode 100644
index 38f51cf4dd..0000000000
--- a/articles/errors/oauth/placeholder.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-public: false
----
-
-# OAuth Errors
\ No newline at end of file
diff --git a/articles/errors/saml/placeholder.md b/articles/errors/saml/placeholder.md
deleted file mode 100644
index 93cc830499..0000000000
--- a/articles/errors/saml/placeholder.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-public: false
----
-
-# SAML Errors
\ No newline at end of file
diff --git a/articles/errors/wsfed/placeholder.md b/articles/errors/wsfed/placeholder.md
deleted file mode 100644
index b8afff3b6c..0000000000
--- a/articles/errors/wsfed/placeholder.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-public: false
----
-
-# WS-Fed Errors
\ No newline at end of file
diff --git a/articles/extend-integrate/index.md b/articles/extend-integrate/index.md
new file mode 100644
index 0000000000..9c187be647
--- /dev/null
+++ b/articles/extend-integrate/index.md
@@ -0,0 +1,60 @@
+---
+classes: topic-page
+title: Extend & Integrate
+description: Learn how to extend the functionality of Auth0's base product and integrate Auth0 with other applications and services.
+topics:
+ - extensions
+ - integrations
+contentType: index
+useCase:
+ - integrate-third-party-apps
+ - integrate-analytics
+ - integrate-marketing
+ - integrate-saas-sso
+ - extensibility-extensions
+---
+
+
+
+
Extend & Integrate
+
+ Learn how to extend the functionality of Auth0's base product and integrate Auth0 with other applications and services.
+
+
+ Rules are JavaScript functions that execute when a user authenticates to your application. They run once the authentication process is complete, and you can use them to customize and extend Auth0's capabilities. Learn how to configure and use rules with Auth0.
+
+ Hooks are secure, self-contained functions that allow you to customize the behavior of Auth0 when executed for selected [extensibility points](/hooks/extensibility-points) of the Auth0 platform. Learn how to configure and use hooks with Auth0.
+
+ Auth0 provides pre-defined extensions that enable you to install applications or run commands/scripts that extend the functionality of the Auth0 base product.
+
+ Add-ons are plugins associated with an application registered with Auth0. Usually, they are third-party APIs used by application(s) for which Auth0 generates Access Tokens (e.g., Salesforce, Azure Service Bus, Windows Azure Mobile Services, SAP).
+
+
+
\ No newline at end of file
diff --git a/articles/extensions/_includes/_batch-size.md b/articles/extensions/_includes/_batch-size.md
new file mode 100644
index 0000000000..139198c627
--- /dev/null
+++ b/articles/extensions/_includes/_batch-size.md
@@ -0,0 +1,16 @@
+### Batch size
+
+When setting your **BATCH_SIZE**, please keep the following information in mind.
+
+During each time frame/window (defined by your chosen **Schedule**), outstanding logs will be batched into groups and sent. The size of each group is determined by the **BATCH_SIZE** value.
+
+In other words, during each window, `NUM_BATCHES` batches of logs will be sent based on the following logic:
+
+```
+IF (NUM_LOGS modulo 100 == 0):
+ NUM_BATCHES = (NUM_LOGS / BATCH_SIZE)
+ELSE:
+ NUM_BATCHES = (NUM_LOGS / BATCH_SIZE) + 1
+```
+
+In the `ELSE` case, the last batch will have < 100 logs.
\ No newline at end of file
diff --git a/articles/extensions/_includes/_deployment-extension.md b/articles/extensions/_includes/_deployment-extension.md
new file mode 100644
index 0000000000..7c3441a6bd
--- /dev/null
+++ b/articles/extensions/_includes/_deployment-extension.md
@@ -0,0 +1,3 @@
+::: note
+The deployment extension accepts an application name instead of the client ID in the `client_id` property. It will try to match the name to an existing application before creating the Client Grant.
+:::
\ No newline at end of file
diff --git a/articles/extensions/_includes/_embedded-clients-array.md b/articles/extensions/_includes/_embedded-clients-array.md
new file mode 100644
index 0000000000..f47346cf5e
--- /dev/null
+++ b/articles/extensions/_includes/_embedded-clients-array.md
@@ -0,0 +1,3 @@
+::: note
+The `enabled_clients` array, when used directly with the Management API v2, is a list of client IDs for which the connection is enabled. As an added convenience, the deployment extension will attempt to match entries in the `enabled_clients` array by client name and replace them with the appropriate client ID when a match is found, allowing you to specify `"my-client-name"` instead of `"my-client-id"` to refer to each application.
+:::
\ No newline at end of file
diff --git a/articles/extensions/_includes/_use-default-error.md b/articles/extensions/_includes/_use-default-error.md
new file mode 100644
index 0000000000..e98dfdcebc
--- /dev/null
+++ b/articles/extensions/_includes/_use-default-error.md
@@ -0,0 +1,3 @@
+::: note
+The `error_page` cannot be enabled/disabled. To use the default error page, remove the content of `error_page.html`.
+:::
diff --git a/articles/extensions/_troubleshoot-webhooks.md b/articles/extensions/_troubleshoot-webhooks.md
index d0f173d98f..fe0a389dc8 100644
--- a/articles/extensions/_troubleshoot-webhooks.md
+++ b/articles/extensions/_troubleshoot-webhooks.md
@@ -6,7 +6,7 @@ However, there are certainly alternatives to the inefficient process we detailed
1. Check the [Logs](/logs) section of the [Dashboard](${manage_url}/#/logs) for helpful messages.
-1. Analyze the requests your webhook is making using a tool like [Hookbin](https://hookbin.com/) or [Mockbin](http://mockbin.org/).
+1. Analyze the requests your webhook is making using a tool like [Mockbin](http://mockbin.org/), [Beeceptor](https://beeceptor.com/), or (self-hosted) [RequestBin](https://github.com/Runscope/requestbin).
1. Mock requests using cURL or [Postman](https://www.getpostman.com/)
diff --git a/articles/extensions/account-link.md b/articles/extensions/account-link.md
index f5691e01b4..6c7e6f8a74 100644
--- a/articles/extensions/account-link.md
+++ b/articles/extensions/account-link.md
@@ -1,8 +1,14 @@
---
-toc: true
description: The Account Link extension allows users with two accounts with the same email to be prompted to link them.
+topics:
+ - extensions
+ - account-linking
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
-# Account Link
+# Account Link Extension
The **Account Link** extension prompts users that may have created a second account by mistake to link the new account with their old one on their first login. The user may choose to either link the two accounts or keep them separate if it was intentional.
@@ -10,9 +16,7 @@ The **Account Link** extension prompts users that may have created a second acco
To install this extension, click on the __Account Link__ box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the dashboard. The __Install Extension__ window will open.
-
-
-The extension will create a new **Application** named `auth0-account-link` to use internally and a new **Rule** to redirect users to the extension if they login with a new account that has an email matching an existing account.
+The extension will create a new **Application** named `auth0-account-link` to use internally and a new **Rule** to redirect users to the extension if they login with a new account that has an email matching an existing account. This application needs to have enabled all the connections that you want to perform account linking with.
## Setup
@@ -22,11 +26,11 @@ We recommend changing the name of the default application used for the extension
### Updating the Login Page
-By default, Auth0's [universal login](/hosted-pages/login) allows a user to both login and sign up as one may expect. However, when the account linking asks you to authenticate your primary account in order to link it with the new account, providing a sign up option can be confusing for users.
+By default, Auth0's [Universal Login](/universal-login) allows a user to both login and sign up as one may expect. However, when the account linking asks you to authenticate your primary account in order to link it with the new account, providing a sign up option can be confusing for users.
To prevent this, we send over a query parameter to let the login page know that it should hide the **Sign Up** option. In order for this query parameter to take effect, however, we must first customize the login page.
-First go to your [Dashboard](${manage_url}) and click on **Hosted Pages**. It should open to the login page by default.
+First go to your [Dashboard](${manage_url}) and click on **Universal Login**. It should open to the login page by default.
If it is not already enabled, toggle the **Customize Login Page** to enable the custom editor below. In the editor we're going to add a new line to the Lock config.
@@ -42,6 +46,10 @@ Then save your changes and attempt to link an account. You'll notice that the **

+:::note
+Hiding the Signup link is not supported in the New Universal Login Experience.
+:::
+
## Customization
At installation, or any time after by clicking the **Settings** icon for the Account Link Extension, you can add a URL to a custom stylesheet if you would like to customize the extension page to look a bit different from the default theme.
@@ -50,10 +58,6 @@ At installation, or any time after by clicking the **Settings** icon for the Acc
## Administration Panel
-::: warning
-This feature is available in version 2.0 and up.
-:::
-
You can customize your account linking login page and widget using the extension administration panel.
Go to **Dashboard > Extensions > Installed Extensions > Auth0 Account Link**.
@@ -71,3 +75,25 @@ Do not remove `{{ ExtensionCSS }}`, `{{ CustomCSS }}`, `{{ Auth0Widget }}`, or `
:::

+
+## Custom domains
+
+If you're using a custom domain, you'll need to update the **auth0-account-link-extension** [rule](/rules) that is automatically created when you installed the extension. (You can find this rule in your Dashboard by going to **Rules** using the left-hand navigation bar).
+
+By default, line 27 of the rule is `issuer: auth0.domain`. You will need to change this to `issuer: "myCustomDomain.com"`, making sure to omit the protocol portion of the URL.
+
+:::note
+Uninstalling/reinstalling, as well as updating, the extension may override this change.
+:::
+
+## How does the extension work?
+
+The extension triggers after authentication, when there is an existing user account using a different provider but with an email address that is the same as that of the user who just authenticated.
+
+For example, if a user logs in with their Facebook account using the email `john@acme.com`, and then later authenticates with Google using the same email address, they will be prompted with a page like this:
+
+
+
+The extension does not automatically link users with the same email, even if emails are verified. Verified emails are not enough evidence to prove that the user can currently authenticate to both accounts.
+
+If the user clicks **Continue**, they will be redirected to Facebook to authenticate. If the user is already logged in, Facebook will redirect back to the application, and the user will be automatically linked. If they are not logged in, they will be prompted first to authenticate with their Facebook credentials. Then, the account will be linked with the Google account after Facebook redirects back to Auth0. This process ensures that it is the same user who has the credentials to authenticate to both accounts. This allows the accounts to be linked safely without fear of linking accounts incorrectly.
diff --git a/articles/extensions/adldap-connector.md b/articles/extensions/adldap-connector.md
index 9ae21de4d5..3d4b011dee 100644
--- a/articles/extensions/adldap-connector.md
+++ b/articles/extensions/adldap-connector.md
@@ -1,8 +1,14 @@
---
description: This page explains the Auth0 AD/LDAP Connector Health Monitor Extension and how to install and configure it.
+topics:
+ - extensions
+ - ad/ldap-connector
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
-# Auth0 Extension: Auth0 AD/LDAP Connector Health Monitor
+# Auth0 AD/LDAP Connector Health Monitor
The Auth0 AD/LDAP Connector Health Monitor exposes an API endpoint of your choice so that you can monitor your AD/LDAP connectors.
diff --git a/articles/extensions/application-insight.md b/articles/extensions/application-insight.md
index c02af1f1b1..b530aa911f 100644
--- a/articles/extensions/application-insight.md
+++ b/articles/extensions/application-insight.md
@@ -1,52 +1,45 @@
---
description: This page explains how to configure and install Auth0's Logs to Application Insights extension.
+topics:
+ - extensions
+ - application-insights
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
-
# Auth0 Logs to Application Insights
The *Auth0 Logs to Application Insights* is a scheduled job takes all of your Auth0 logs and exports them to [Application Insights](https://azure.microsoft.com/en-us/services/application-insights/).
## Configure the Extension
-To install and configure this extension, click on the __Auth0 Logs to Application Insights__ box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the [dashboard](${manage_url}). The __Install Extension__ window pops open.
-
-
+To install and configure this extension, click on the __Auth0 Logs to Application Insights__ box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the [Dashboard](${manage_url}).
-At this point you should set the following configuration variables:
+The __Install Extension__ window pops open, and you will be asked to set the following configuration variables:
- __Schedule__: The frequency with which logs should be exported.
-- __Batch_Size__: TThe amount of logs to be read on each execution. Maximun is 100.
-- __AppInsights_Instrumentation_Key__: The Application Insights instrumentation key.
-
- Once you have provided the appropriate values for the above fields, click __Install__ to proceed.
-
-## Retrieve the required information from Application Insights
-
-Let's see how we can retrieve the __AppInsights_Instrumentation_Key__ information.
+- __Batch_Size__: The amount of logs to be read on each execution. Maximum is 100.
+- __Start_From__: The ID of the log that you want to start sending from
+- __Slack_Incoming_Webhook_URL__: The Slack webhook URL that you want to use to receive notifications regarding your log-sending process
+- __Slack_Send_Success__: If yes, Auth0 will send verbose notifications to Slack
+- __Log_Level__: The log level of events to be sent; Auth0 will send all logs at the selected above and higher
+- __Log_Types__: The types of logs you want send; leave blank to send all log events
+- __AppInsights_Instrumentation_Key__: The Application Insights instrumentation key (see the following section for information on obtaining the instrumentation key if you do not already have it)
-1. Login to your [Azure Portal](https://portal.azure.com/#) and add a new _Application Insights_ instance in your subscription. To do so click __New__ and search for `Application Insights`.
+ When done, click __Install__ to proceed.
-
+ <%= include('./_includes/_batch-size') %>
-2. Click __Create__ and fill in the required information, such as the name of your instance, the application type and the resource group. Click __Create__ to trigger the provisioning process.
-
-
-
-3. Once the provisioning is complete (after a few seconds usually) you can get the __Instrumentation Key__ from the Properties page.
-
-
-
-4. Copy this value and head back to your [Auth0 dashboard](${manage_url}). Set it at the __AppInsights_Instrumentation_Key__ field. Save your changes.
+## Retrieve the required information from Application Insights
+When configuring the extension, you'll be asked by Auth0 to provide the [instrumentation key](https://docs.microsoft.com/en-us/azure/azure-monitor/app/create-new-resource#copy-the-instrumentation-key) for Application Insights. You will need to have [created an Application Insights resource](https://docs.microsoft.com/en-us/azure/azure-monitor/app/create-new-resource#copy-the-instrumentation-key) with Azure before you can obtain this value.
## Use Your Installed Extension
-To view all scheduled jobs, navigate to the [Extensions](${manage_url}/#/extensions) page of the [dashboard](${manage_url}), click on the __Installed Extensions__ link, and select the __Auth0 Logs to Application Insights__ line. There you can see the job you just created, modify its state by toggling the __State__ switch, see when the next run is due and what was the result of the last execution.
-
-
+To view all scheduled jobs, navigate to the [Extensions](${manage_url}/#/extensions) page of the [Dashboard](${manage_url}). Click on the __Installed Extensions__ link, and select the __Auth0 Logs to Application Insights__ line.
-You can view more details by clicking on the job you created. In this page you can view details for each execution, reschedule, access realtime logs, and more.
+There, you can see the job you just created, modify its state by toggling the __State__ switch, and see when the next run is due and what was the result of the last execution.
-
+You can view more details by clicking on the job you created. On this page you can view details for each execution, reschedule, access real-time logs, and more.
-That's it, you are done! You can now navigate to your [Azure Portal](https://portal.azure.com/#) and view your [Auth0 Logs](${manage_url}/#/logs).
+At this point, you can navigate to your [Azure Portal](https://portal.azure.com/#) to view your [Auth0 Logs](${manage_url}/#/logs).
diff --git a/articles/extensions/authentication-api-debugger.md b/articles/extensions/authentication-api-debugger.md
index 195143f5d5..bb6b1fdf26 100644
--- a/articles/extensions/authentication-api-debugger.md
+++ b/articles/extensions/authentication-api-debugger.md
@@ -1,5 +1,11 @@
---
description: This page explains how to use the Authentication API Debugger
+topics:
+ - extensions
+ - auth-api-debugger
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Authentication API Debugger Extension
diff --git a/articles/extensions/authentication-api-webhooks.md b/articles/extensions/authentication-api-webhooks.md
index a4a05f6797..b1fe440de1 100644
--- a/articles/extensions/authentication-api-webhooks.md
+++ b/articles/extensions/authentication-api-webhooks.md
@@ -1,5 +1,11 @@
---
description: This page explains how to configure and install Auth0's Authentication API Webhooks extension.
+topics:
+ - extensions
+ - auth-api-webhooks
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Authentication API Webhooks
@@ -11,12 +17,14 @@ The Auth0 Authentication API Webhooks Extension is a scheduled job that allows y
To complete installation of this extension, click on the Auth0 Authentication API Webhooks box in the list of provided extensions on the Extensions page of the Management Portal. In the "Install Extension" window that then pops open, you will be asked to provide the following configuration variables:
- __Schedule__: The frequency with which the job runs
-- __Auth0_Domain__: The domain of your Auth0 app
-- __Auth0_Global_Client_ID__: The Client ID of your Auth0 app
-- __Auth0_Global_Client_Secret__: The Client Secret of your Auth0 app
-- __Auth0_API_Endpoints__: The specific Auth0 Management API endpoints you want to monitor/call
-- __Webhook URL__: The URL of your webhook
-- __Webhook_Concurrent_Calls__: The maximum number of concurrent calls that will be made to your webhook
+- __Batch_Size__: The amount of logs the extension will attempt to read and send on each execution. Extension could send multiple batches per run, depending on amount of time necessary to process. Maximum batch size is 100.
+- __Webhook_URL__: The URL of your webhook
+- __Authorization__: String to be added as `Authorization` header.
+- __Send_as_Batch__: If enabled, the extension will send the whole batch of logs to the webhook in a single request. Otherwise, extension sends logs one-by-one to webhook. Only disable if your webhook does not support batched messages.
+- __Webhook_Concurrent_Calls__: The maximum number of concurrent calls that will be made to your webhook.
+- __Start_From__: Log Checkpoint to start from.
+- __Slack_Incoming_Webhook_URL__: Extension can report statistics and possible failures to the Slack.
+- __Slack_Send_Success__: If enabled, extension will be sending messages on each run. Otherwise - only on fails.
- __Log_Level__: The minimal log level of events that you would like sent
- __Log_Types__: The specific events for which logs should be exported
@@ -64,4 +72,4 @@ Here is an example of the payload that will be sent:
}
```
-<%= include('./_troubleshoot-webhooks') %>
\ No newline at end of file
+<%= include('./_troubleshoot-webhooks') %>
diff --git a/articles/extensions/authorization-extension/v1/index.md b/articles/extensions/authorization-extension/v1/index.md
index 75935b5d39..eefc569539 100644
--- a/articles/extensions/authorization-extension/v1/index.md
+++ b/articles/extensions/authorization-extension/v1/index.md
@@ -1,5 +1,12 @@
---
description: This page explains how to setup and manage the Authorization Extension v1.
+topics:
+ - extensions
+ - authorization_v1
+contentType:
+ - tutorial
+ - concept
+useCase: extensibility-extensions
---
# Auth0 Authorization Extension v1
@@ -8,7 +15,7 @@ description: This page explains how to setup and manage the Authorization Extens
This document covers an outdated version. We recommend you to [upgrade to v2](/extensions/authorization-extension/v2).
:::
-The Auth0 Authorization Extension provides user authorization support in Auth0. Version 1 of the extension supports authorizations using Groups. Upgrade to [version 2](/extensions/authorization-extension) to support authorizations with Roles and Permissions.
+The Auth0 Authorization Extension provides user authorization support in Auth0. Version 1 of the extension supports authorizations using Groups. Upgrade to [version 2](/extensions/authorization-extension) to support authorizations with Roles and Permissions.
## Setting Up a New Authorization Extension
diff --git a/articles/extensions/authorization-extension/v2/api-access.md b/articles/extensions/authorization-extension/v2/api-access.md
index 211293e8de..c724cb1f4c 100644
--- a/articles/extensions/authorization-extension/v2/api-access.md
+++ b/articles/extensions/authorization-extension/v2/api-access.md
@@ -1,10 +1,21 @@
---
title: Enabling API Access to the Authorization Extension
description: How to enable API access to the Authorization Extension
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension: API Access
-Once configured and set up, your extension should contain users, as well as groups, roles, and permissions. You can automate provisioning and query the authorization context of your users in real-time if you enable API access to your extension.
+::: note
+<%= include('../../../_includes/_rbac_methods') %>
+:::
+
+Once configured and set up, your extension should contain users, as well as groups, roles, and permissions. You can automate provisioning and query the authorization context of your users in real-time if you enable API access to your extension.
## Enable API Access
@@ -34,27 +45,27 @@ You'll be redirected to the **Quick Start** page of the Application, where you c
Since this is the first time you're working with the API and Application together, you'll see a message that says, "This application is not authorized for this API." To authorize the application for use with the API, click **Navigate to the API and Authorize**.
-
+
You'll see a list of Machine to Machine Applications you can use with your API. Click the slider next to the Application you just created to authorize it.
-
+
Once you've authorized the Application, you'll see the **Grant ID**. You can also select the **Scopes** to be granted to the Application. The scopes you grant depends on the endpoints you want to access. For example, you'd grant `read:users` to [get all users](hapi/authorization-extension#get-all-users).
If you make any changes to the scopes, click **Update** to save.
-
+
### Get the Access Token
-To access the API, you'll need to [ask for and obtain the appropriate token](https://auth0.com/docs/api-auth/tutorials/client-credentials#ask-for-a-token).
+To access the API, you'll need to [ask for and obtain the appropriate token](/flows/guides/client-credentials/call-api-client-credentials#request-token).
### Call the API
You can call the API via:
-* An HTTML request
+* An HTML request
* A cURL command
You can also find detailed information about the endpoints, as well as samples on how to call each endpoint using the three methods above, in the [Authorization Extension API Explorer](/api/authorization-extension).
@@ -71,4 +82,4 @@ Click over to the **Explorer** page for the API documentation.
* [Use the Authorization Extension's Data in Rules](/extensions/authorization-extension/v2/rules)
* [Import/Export Data](/extensions/authorization-extension/v2/import-export-data)
* [Troubleshoot Errors](/extensions/authorization-extension/v2/troubleshooting)
-:::
\ No newline at end of file
+:::
diff --git a/articles/extensions/authorization-extension/v2/implementation/configuration.md b/articles/extensions/authorization-extension/v2/implementation/configuration.md
index 56e6a5a7fc..8182bf0e25 100644
--- a/articles/extensions/authorization-extension/v2/implementation/configuration.md
+++ b/articles/extensions/authorization-extension/v2/implementation/configuration.md
@@ -2,10 +2,21 @@
title: Configuring the Authorization Extension
description: How to configure the Authorization Extension
toc: true
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension: Configuration
+::: note
+<%= include('../../../../_includes/_rbac_methods') %>
+:::
+
Before the extension can enforce your authorization logic, you'll need to configure how it will behave during the login transaction. Your configuration settings will be captured in a [rule](/rules) that's executed during runtime.
## Configure the Extension
@@ -18,7 +29,13 @@ This brings you to the **Rule Configuration** section of the **Configuration** p

-All of the changes you make in the sections under **Token Contents**, such as those related to groups, roles, and permissions, will be reflected in the rule you export at the completion of this step.
+All of the changes you make in the sections under **Token Contents**, such as those related to groups, roles, and permissions, will be reflected in the rule you export at the completion of this step.
+
+### ApiKey
+
+The rule is using ApiKey to communicate with the Authorization Extension API and can be used only to get the policy. ApiKey is stored as a rule config and it will be created automatically when the rule is published. You can rotate the ApiKey by pressing the "Rotate" button. It will update the rule config automatically.
+
+
## Add Authorization Information to the Token Issued
@@ -68,4 +85,4 @@ You can open it up to see the exact rules configuration.
* [Use the Authorization Extension's Data in Rules](/extensions/authorization-extension/v2/rules)
* [Troubleshoot Errors](/extensions/authorization-extension/v2/troubleshooting)
* [Set Up the Authorization Extension](/extensions/authorization-extension/v2/implementation/setup)
-:::
\ No newline at end of file
+:::
diff --git a/articles/extensions/authorization-extension/v2/implementation/installation.md b/articles/extensions/authorization-extension/v2/implementation/installation.md
index a324a556d6..5d74a9501f 100644
--- a/articles/extensions/authorization-extension/v2/implementation/installation.md
+++ b/articles/extensions/authorization-extension/v2/implementation/installation.md
@@ -2,16 +2,27 @@
title: Installing the Authorization Extension
description: How to install the Authorization Extension
toc: true
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension: Installation
+::: note
+<%= include('../../../../_includes/_rbac_methods') %>
+:::
+
This doc walks you through the process of installing the Authorization Extension.
Before you begin, make sure that you have an existing [application](/application) that can be used with the Authorization Extension. Currently, you can use the following types of applications:
* Native
* Regular Web Applications
-* Single Page Applications
+* Single-Page Applications
Applications without an assigned type or Machine to Machine Applications cannot be used with this extension.
@@ -73,7 +84,7 @@ This extension has limitations in terms of performance and is not meant to be us
```
::: note
-Amazon S3 is a file-based storage platform, which means it writes in parallel. This may cause issues, but the extension's storage logic attempts to take this into account. However, if you automate the creation of groups/roles/permissions, we suggest that you do so using sequential calls to the API.
+Amazon S3 is a file-based storage platform, which means it writes in parallel. This may cause issues, but the extension's storage logic attempts to take this into account. However, if you automate the creation of groups/roles/permissions, we suggest that you do so using sequential calls to the API.
:::

diff --git a/articles/extensions/authorization-extension/v2/implementation/setup.md b/articles/extensions/authorization-extension/v2/implementation/setup.md
index 12599f5f7a..513be6bc06 100644
--- a/articles/extensions/authorization-extension/v2/implementation/setup.md
+++ b/articles/extensions/authorization-extension/v2/implementation/setup.md
@@ -2,11 +2,22 @@
title: Setting Up the Authorization Extension
description: How to set up the Authorization Extension
toc: true
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension: Setup
-In this paragraph, we'll briefly cover the basics of users, groups, roles, and permissions.
+::: note
+<%= include('../../../../_includes/_rbac_methods') %>
+:::
+
+In this article we'll cover the basics of users, groups, roles, and permissions.
Let's say that you have an application that is accessible to everyone within your corporation. The **users** are the individuals to whom you'd like to grant access to your application.
@@ -39,7 +50,7 @@ Rather than assigning both permissions to groups/users, you can roll the two (al
## Users
-The **Users** section lists all the current users of your applications. You can use this to search for and select a specific user to see their profile, view or edit their group affiliations, and view or edit their roles.
+The **Users** section lists all the current users of your applications. Here you can find a specific user, see their profile, change their group affiliations, and change their roles.

@@ -105,7 +116,7 @@ You can create different types of Roles such as: Expense Admins, Expense Manager

-To add a role, click the **CREATE ROLE** button from the **Roles** section of the dashboard. Then choose the application this Role applies to (such as Expense Management Tool) and then add a name of the role (such as Expense Admins) and a description of the role. Then select the permissions you wish to grant to this role. If you haven't yet created your permissions you can add them later to an exisiting Role.
+To add a role, click the **CREATE ROLE** button from the **Roles** section of the dashboard. Then choose the application this Role applies to (such as Expense Management Tool) and then add a name of the role (such as Expense Admins) and a description of the role. Then select the permissions you wish to grant to this role. If you haven't yet created your permissions you can add them later to an existing Role.

diff --git a/articles/extensions/authorization-extension/v2/import-export-data.md b/articles/extensions/authorization-extension/v2/import-export-data.md
index d540b48fc7..2486b60091 100644
--- a/articles/extensions/authorization-extension/v2/import-export-data.md
+++ b/articles/extensions/authorization-extension/v2/import-export-data.md
@@ -1,14 +1,25 @@
---
title: Importing Data Into and Exporting Data from the Authorization Extension
description: How to import/export Authorization Extension Data
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension: Import/Export Data
+::: note
+<%= include('../../../_includes/_rbac_methods') %>
+:::
+
You can import new data from or export existing authorization data to a JSON file. This can be useful when moving environments.
::: warning
-Roles and permissions are linked to specific applications. If you export your JSON file and import it into a different environment, you will need to change the client ID for these records.
+Roles and permissions are linked to specific applications. If you export your JSON file and import it into a different environment, you will need to change the client ID for these records.
:::
You can get to the **Import/Export** section by clicking **Configuration** on the drop-down menu accessible by clicking on your tenant name at the top right of the **Authorization Dashboard**.
diff --git a/articles/extensions/authorization-extension/v2/index.md b/articles/extensions/authorization-extension/v2/index.md
index 34520d7d2a..90af84435f 100644
--- a/articles/extensions/authorization-extension/v2/index.md
+++ b/articles/extensions/authorization-extension/v2/index.md
@@ -3,13 +3,61 @@ toc: true
classes: topic-page
title: Authorization Extension
description: Control user authorization behavior during runtime with the Authorization Extension
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension
-The Authorization Extension provides support for user authorization via Groups, Roles, and Permissions. You can define the expected behavior during the login process, and your configuration settings will be captured in a [rule](/rules) that's executed during runtime.
+::: panel Breaking Changes
+Authorization Extension 2.6 contains breaking changes that result from changed logic for storing and handling the API Key; these require you to perform additional steps upon upgrade, as detailed below. Failing to complete these steps will result in either an `InvalidApiKey` or `You are not allowed to access this application` error on rule execution. For more info, see the [changelog](https://github.com/auth0/auth0-authorization-extension/blob/master/CHANGELOG.md).
-You can store authorization data like groups, roles, or permissions in the outgoing token issued by Auth0. Your application can then consume this information by inspecting the token and take appropriate actions based on the user's current authorization context.
+Upgrades from version 2.6 or later do not have breaking changes and require no further action.
+
+**If you are upgrading from a version before 2.6, you must:**
+
+Upgrade the Authorization Extension
+
+1. Navigate to the [Extensions](${manage_url}/#/extensions) page in the [Auth0 Dashboard](${manage_url}), and click the **Installed Extensions** tab.
+2. Locate **Auth0 Authorization**, click **Upgrade**, and confirm. Wait for the upgrade to complete.
+
+Rotate the extension's API Key
+
+1. Click on **Auth0 Authorization** to open the extension.
+2. From the dropdown menu in the top-right of the extension dashboard, select **Configuration**.
+3. Locate the **API Key** section, and click **Rotate**.
+
+Republish the extension's Rule
+
+1. Click **Publish Rule**.
+
+Delete the old extension Rule, if it exists
+
+1. Navigate to the [Rules](${manage_url}/#/rules) page in the [Auth0 Dashboard](${manage_url})
+2. Locate the `auth0-authz` rule. If it does not exist, you are done.; otherwise, continue with these steps:
+3. Locate the `auth0-authorization-extension` rule and drag it into the position below the `auth0-authz` rule.
+4. Check that the `auth0-authz` rule:
+ * was authored by the Authorization Extension and has not been modified manually
+ * will not change the authorization flow in a way that will grant access or privileges to undesired users if it is removed
+5. If the above conditions are true, use the toggle to disable the `auth0-authz` rule. After verifying that everything works appropriately, you can decide whether to leave the rule disabled or remove it entirely.
+:::
+
+::: note
+<%= include('../../../_includes/_rbac_methods') %>
+:::
+
+<%= include('../../../_includes/_rbac_vs_extensions') %>
+
+The Authorization Extension provides support for user authorization via Groups, Roles, and Permissions. You can define the expected behavior during the login process, and your configuration settings will be captured in a [rule](/rules) that's executed during runtime.
+
+With the Authorization Extension, you can store authorization data like groups, roles, or permissions in the outgoing token issued by Auth0. Your application can then consume this information by inspecting the token and take appropriate actions based on the user's current authorization context.
+
+With the Authorization Extension, roles and permissions are set on a per-application basis. If you need the same roles or permissions on another application, you'll have to create them separately. Conversely, the [Authorization Core](/authorization/concepts/core-vs-extension) feature set provides much more flexibility with roles and permissions.
## Get Started
diff --git a/articles/extensions/authorization-extension/v2/migration.md b/articles/extensions/authorization-extension/v2/migration.md
index 4ef03613c2..fb2d873770 100644
--- a/articles/extensions/authorization-extension/v2/migration.md
+++ b/articles/extensions/authorization-extension/v2/migration.md
@@ -1,10 +1,21 @@
---
title: Installing the Authorization Extension v2
description: How to install the Authorization Extension v2
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension: Migrate from Version 1 to Version 2
+::: note
+<%= include('../../../_includes/_rbac_methods') %>
+:::
+
::: warning
Migrating from Version 1 to Version 2 is a breaking change
:::
diff --git a/articles/extensions/authorization-extension/v2/rules.md b/articles/extensions/authorization-extension/v2/rules.md
index 4a01391891..5a9fc25412 100644
--- a/articles/extensions/authorization-extension/v2/rules.md
+++ b/articles/extensions/authorization-extension/v2/rules.md
@@ -2,22 +2,33 @@
title: Using Rules with the Authorization Extension
description: How to use information from the extension in rules
toc: true
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
---
# Authorization Extension: Rules
+::: note
+<%= include('../../../_includes/_rbac_methods') %>
+:::
+
You can use [rules](/rules) with the Authorization Extension to do things like:
-* Add [custom claims](/scopes/current#custom-claims) to the issued token
-* Determining the user's group membership, roles and permissions
+* Add [custom claims](/tokens/concepts/jwt-claims#custom-claims) to the issued token
+* Determining the user's group membership, roles and permissions
* Storing the user's groups, roles and permissions info as [part of the `app_metadata`](/extensions/authorization-extension/v2/configuration#persistence)
-* Adding the user's groups, roles and permissions to the [outgoing token]((/extensions/authorization-extension/v2/configuration#token-contents)) (which can be requested via the `openid groups permissions roles` scope)
+* Adding the user's groups, roles and permissions to the [outgoing token](/extensions/authorization-extension/v2/configuration#token-contents) (which can be requested via the `openid groups permissions roles` scope)
Because the above logic is part of a rule, it will only be executed in the context of a login. If users are added to or removed from a group, this change will only be reflected in Auth0 after the user's next login.
## Add Custom Claims to the Issued Token
-If you'd like to add custom claims to your tokens, you can do so by creating additional [rule](/rules) that allows the Authorization Extension to do so.
+If you'd like to add custom claims to your tokens, you can do so by creating additional [rule](/rules) that allows the Authorization Extension to do so. Custom claims should be [namespaced](/tokens/guides/create-namespaced-custom-claims).
::: note
You should [limit the number of claims](/extensions/authorization-extension/v2/configuration#data-limitations) you add to the token.
@@ -48,7 +59,7 @@ You can also write rules that are executed after the Authorization Extension rul
### Step 1: Set the Application Metadata's `required_roles`
-In this step, you'll set the Application's metadata with it's roles, which are groups of permissions that you've grouped together to create a specific set of functionality. You can think of this step as "tagging" the Application so that the rules you'll set up in the next step know which Application to act on.
+In this step, you'll set the Application's metadata with its roles, which are groups of permissions that you've grouped together to create a specific set of functionality. You can think of this step as "tagging" the Application so that the rules you'll set up in the next step know which Application to act on.
1. To set the `context.clientMetadata` field with `required_roles`, begin by selecting the application you want to work with [in the dashboard](${manage_url}/#/applications).
@@ -101,4 +112,4 @@ function (user, context, callback) {
* [Import/Export Data](/extensions/authorization-extension/v2/import-export-data)
* [Troubleshoot Errors](/extensions/authorization-extension/v2/troubleshooting)
* [Enable API Access to the Extension](/extensions/authorization-extension/v2/api-access)
-:::
\ No newline at end of file
+:::
diff --git a/articles/extensions/authorization-extension/v2/troubleshooting.md b/articles/extensions/authorization-extension/v2/troubleshooting.md
index 479c325880..2d54316712 100644
--- a/articles/extensions/authorization-extension/v2/troubleshooting.md
+++ b/articles/extensions/authorization-extension/v2/troubleshooting.md
@@ -1,18 +1,32 @@
---
-title: Troubleshooting the Authorization Extension
-description: How to troubleshoot the Authorization Extension
+title: Troubleshoot the Authorization Extension
+description: Learn how to troubleshoot the Authorization Extension,
+topics:
+ - extensions
+ - authorization_v2
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
-# Authorization Extension: Troubleshoot Issues
+# Troubleshoot the Authorization Extension
+
+::: note
+<%= include('../../../_includes/_rbac_methods') %>
+:::
The following are some issues you might see when setting up the Authorization Extension, as well as some tips to help you identify the cause.
## The authentication results in a token that contains groups information, but not roles or permissions information.
-If this happens, chances are that you created roles and permissions for one application, but your users are authenticating using another application. For example, let's say that you created all your roles/permissions against Website A. However, you also create another website application in Auth0 for Website B. Then, you use the `client_id` and `client_secret` for Website B, instead of those for Website A, in your app.
+If this happens, chances are that you created roles and permissions for one application, but your users are authenticating using another application. For example, let's say that you created all your roles/permissions against Website A. However, you also create another website application in Auth0 for Website B. Then, you use the `client_id` and `client_secret` for Website B, instead of those for Website A, in your app.
Alternatively, you might see this if you click the **Try** button in the Auth0 Dashboard on a Connection that contains one of your users. This will execute an authentication flow using the Auth0 _global application_, but this is not the same as the application you configured in the extension.
## My application is not shown in the drop-down menu when setting up the extension.
-The supported application types for the Authorization extension are: **Native**, **Single Page Web Applications** and **Regular Web Applications**. Applications with no type assigned and **Machine to Machine Applications** are not supported.
\ No newline at end of file
+The supported application types for the Authorization extension are: **Native**, **Single-Page Web Applications** and **Regular Web Applications**. Applications with no type assigned and **Machine to Machine Applications** are not supported.
+
+## I upgraded to v2 and my users get an error upon login
+
+If you see the error `You are not allowed to access this application`, most probably there is some conflict with the old rule. Turn off the persistence settings, delete the existing rule, re-enable the settings, and test again.
diff --git a/articles/extensions/azure-blob-storage.md b/articles/extensions/azure-blob-storage.md
index 150b17c26c..d4c14196f0 100644
--- a/articles/extensions/azure-blob-storage.md
+++ b/articles/extensions/azure-blob-storage.md
@@ -1,5 +1,12 @@
---
description: This page explains how to configure and use Auth0's extension for Auth0 Logs to Azure Blob Storage.
+topics:
+ - extensions
+ - azure
+ - blob-storage
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Logs to Azure Blob Storage
@@ -26,6 +33,8 @@ At this point you should set the following configuration variables:
Once you have provided this information, click the *Install* button to finish installing the extension.
+<%= include('./_includes/_batch-size') %>
+
## Retrieve the required information from Azure Portal
We need the following information: Account Name, Account Key, and Container Name. Let's see how we can retrieve these values from Azure Portal.
@@ -36,7 +45,9 @@ Log into your Azure account and click on __Storage accounts__ on the left-hand s
The __Account Name__ is the name of your storage account, the one we created is named `azureauth0logs`.
-This value should be set as __Storage_Account_Name__.
+This value should be set as __Storage_Account_Name__.
+
+The value **Kind** should be set as **Storage**.

@@ -54,8 +65,7 @@ Click on the __Access keys__ tab. Here you can find the value for __Storage_Acco
Now that you have retrieved all three values head back to the [Auth0 dashboard](${manage_url}) and set them at the corresponding fields. You 're done!
-
-## Use Your Installed Extension
+## Use installed Extension
To view all scheduled jobs, navigate to the [Extensions](${manage_url}/#/extensions) page, click on the __Installed Extensions__ link, and select the __Auth0 Logs to Azure Blob Storage__ line. There you can see the job you just created, modify its state by toggling the __State__ switch, see when the next run is due and what was the result of the last execution.
diff --git a/articles/extensions/bitbucket-deploy.md b/articles/extensions/bitbucket-deploy.md
index c05a2580fc..c597432fed 100644
--- a/articles/extensions/bitbucket-deploy.md
+++ b/articles/extensions/bitbucket-deploy.md
@@ -1,11 +1,17 @@
---
toc: true
description: The Bitbucket Deployments extension allows you to deploy Rules and Database Connection scripts from Bitbucket to Auth0.
+topics:
+ - extensions
+ - bitbucket-deployments
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Bitbucket Deployments
-The **Bitbucket Deployments** extension allows you to deploy [Rules](/rules) and Database Connection scripts from Bitbucket to Auth0. You can configure a Bitbucket repository, keep all of your Rules and Database Connection scripts there, and have them automatically deployed to Auth0 whenever you push changes to your repository.
+The **Bitbucket Deployments** extension allows you to deploy [rules](/rules), rules configs, connections, database connection scripts, clients, client grants, resource servers, Universal Login pages and email templates from Bitbucket to Auth0. You can configure a Bitbucket repository, keep all of your Rules and Database Connection scripts there, and have them automatically deployed to Auth0 whenever you push changes to your repository.
## Configure the Extension
@@ -15,11 +21,17 @@ To install and configure this extension, click on the **Bitbucket Deployments**
Set the following configuration variables:
-* **BITBUCKET_REPOSITORY**: the repository from which you want to deploy your Rules and Database Connection scripts (this can be either a public or private repository);
-* **BITBUCKET_BRANCH**: the branch the extension will monitor for changes;
-* **BITBUCKET_USER**: the username used to access the Bitbucket account;
-* **BITBUCKET_PASSWORD**: the password associated with the username used to access the Bitbucket account;
-* **SLACK_INCOMING_WEBHOOK**: the Webhook URL for Slack used to notify you of successful and failed deployments.
+* **REPOSITORY**: The repository from which you want to deploy your Rules and Database Connection scripts. This can be either a public or private repository
+* **BRANCH**: The branch the extension will monitor for changes
+* **USER**: The username used to access the Bitbucket account. Make sure you use the username, and not the email
+* **PASSWORD**: The user password or an app password you create through the Bitbucket settings to grant permissions to certain apps (`Repositories: Read` permission is required)
+* **BASE_DIR**: The base directory, where all your tenant settings are stored
+* **AUTO_REDEPLOY**: If enabled, the extension redeploys the last successful configuration in the event of a deployment failure. Manual deployments and validation errors does not trigger auto-redeployment
+* **SLACK_INCOMING_WEBHOOK**: The Webhook URL for Slack used to notify you of successful and failed deployments
+
+::: note
+Some of the configuration variables were changed in version **2.6.0** of this extension. If you are updating the extension from a prior version, make sure that you update your configuration accordingly.
+:::
Once you have provided this information, click **Install**.
@@ -45,7 +57,16 @@ You can find details on how to configure a webhook at [Creating Webhooks](https:
Once you have set up the webhook in Bitbucket using the provided information, you are ready to start committing to your repository.
-With each commit you push to your configured Bitbucket repository, the webhook will call the extension to initiate a deployment if changes were made to the `rules` and/or the `database-connection` folders.
+With each commit you push to your configured Bitbucket repository, the webhook will call the extension to initiate a deployment if changes were made to one of these folders:
+- `clients`
+- `grants`
+- `emails`
+- `resource-servers`
+- `connections`
+- `database-connections`
+- `rules-configs`
+- `rules`
+- `pages`
The **Deploy** button on the **Deployments** tab of the extension allows you to manually deploy the Rules and Database Connection scripts that you already have in your Bitbucket repository. This is useful if your repository already contains items that you want to deploy once you have set up the extension or if you have accidentally deleted some scripts in Auth0 and need to redeploy the latest version of your repository.
@@ -70,22 +91,55 @@ For a generic Custom Database Connection, only the `login.js` script is required
You can find examples in [the Auth0 Samples repository](https://github.com/auth0-samples/github-source-control-integration/tree/master/database-connections/my-custom-db). While the samples were authored for GitHub, it will work for a Bitbucket integration as well.
-### Deploy Hosted Pages
+#### Deploy Database Connection Settings
+
+To deploy Database Connection settings, you must create `database-connections/[connection-name]/database.json`.
+
+_This will work only for Auth0 connections (strategy === auth0); for non-Auth0 connections use `connections`._
+
+_Support for using `settings.json` has been deprecated in favor of `database.json` since v3.1.1 of the extension and may be dropped in a future release._
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Connections/patch_connections_by_id) for more info on allowed attributes for Connections.
+
+### Deploy Connections
+
+To deploy a connection, you must create a JSON file under the `connections` directory of your Bitbucket repository. Example:
+
+__facebook.json__
+```json
+{
+ "name": "facebook",
+ "strategy": "facebook",
+ "enabled_clients": [
+ "my-client"
+ ],
+ "options": {}
+}
+```
+
+<%= include('./_includes/_embedded-clients-array') %>
+
+_This will work only for non-Auth0 connections (`strategy !== auth0`); for Auth0 connections, use `database-connections`._
+
+For more info on the allowed attributes for connections, see the [Post Connections endpoint] (/api/management/v2#!/Connections/post_connections).
+
+### Deploy Universal Login Pages
+
+The supported pages are:
-The supported hosted pages are:
- `error_page`
- `guardian_multifactor`
- `login`
- `password_reset`
-To deploy a page, you must create an HTML file under the `pages` directory of your Bitbucket repository. For each HTML page you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, in order to deploy an `error_page`, you would create two files:
+To deploy a page, you must create an HTML file under the `pages` directory of your Bitbucket repository. For each HTML page, you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, to deploy a `password_reset`, you would create two files:
```text
-your-bitbucket-repo/pages/error_page.html
-your-bitbucket-repo/pages/error_page.json
+your-bitbucket-repo/pages/password_reset.html
+your-bitbucket-repo/pages/password_reset.json
```
-To enable the page the `error_page.json` would contain the following:
+To enable the page, the `password_reset.json` would contain the following:
```json
{
@@ -93,9 +147,11 @@ To enable the page the `error_page.json` would contain the following:
}
```
+<%= include('./_includes/_use-default-error') %>
+
### Deploy Rules
-To deploy a rule, you must first create a JavaScript file under the `rules` directory of your Bitbucket repository. Each Rule must be in its own `.js` file.
+To deploy a rule, you must first create a JavaScript file under the `rules` directory of your Bitbucket repository. Each Rule must be in its own JavaScript file.
For example, if you create the file `rules/set-country.js`, the extension will create a Rule in Auth0 with the name `set-country`.
@@ -103,10 +159,6 @@ For example, if you create the file `rules/set-country.js`, the extension will c
If you plan to use source control integration for an existing account, first rename your Rules in Auth0 to match the name of the files you will be deploying to this directory.
:::
-You can mark rules as manual. In that case, the source control extension will not delete or update them. To mark a rule navigate to the **Rules Configuration** tab of the **Bitbucket Integration** page. Toggle the **Manual Rule** switch for the rules you want to mark as manual. Click **Update Manual Rules** to save your changes.
-
-
-
You can control the Rule order and status (`enabled`/`disabled`) by creating a JSON file with the same name as your JavaScript file. For this example, you would create a file named `rules/set-country.json`.
__set-country.js__
@@ -120,7 +172,7 @@ function (user, context, callback) {
```
__set-country.json__
-```javascript
+```json
{
"enabled": false,
"order": 15,
@@ -132,7 +184,158 @@ You can find a `login_success` example in [the Auth0 Samples repository](https:/
#### Set Rule Order
-To avoid conflicts, you are cannot set multiple Rules of the same order. However, you can create a JSON file for each rule, and within each file, assign a value for `order`. We suggest using number values that allow for reordering with less risk for conflict. For example, assign a value of `10` to the first Rule and `20` to the second Rule, rather than using values of `1` and `2`, respectively).
+To avoid conflicts, you cannot set multiple Rules of the same order. However, you can create a JSON file for each rule, and within each file, assign a value for `order`. We suggest using number values that allow for reordering with less risk of conflict. For example, assign a value of `10` to the first Rule and `20` to the second Rule, rather than using values of `1` and `2`, respectively).
+
+### Deploy Rules Configs
+
+To deploy a rule config, you must create a JSON file under the `rules-configs` directory of your Bitbucket repository. Example:
+
+__secret_number.json__
+```json
+{
+ "key": "secret_number",
+ "value": 42
+}
+```
+
+### Deploy Clients
+
+To deploy a client, you must create a JSON file under the `clients` directory of your Bitbucket repository. Example:
+
+__my-client.json__
+```json
+{
+ "name": "my-client"
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Clients/post_clients) for more info on allowed attributes for Clients and Client Grants.
+
+### Deploy Clients Grants
+
+You can specify the client grants for each client by creating a JSON file in the `grants` directory.
+
+__my-client-api.json__
+```json
+{
+ "client_id": "my-client",
+ "audience": "https://myapp.com/api/v1",
+ "scope": [
+ "read:users"
+ ]
+}
+```
+
+<%= include('./_includes/_deployment-extension') %>
+
+### Deploy Resource Servers
+
+To deploy a resource server, you must create a JSON file under the `resource-servers` directory of your Bitbucket repository. Example:
+
+__my-api.json__
+```json
+{
+ "name": "my-api",
+ "identifier": "https://myapp.com/api/v1",
+ "scopes": [
+ {
+ "value": "read:users",
+ "description": "Allows getting user information"
+ }
+ ]
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Resource_Servers/post_resource_servers) for more info on allowed attributes for Resource Servers.
+
+### Deploy Email Provider
+
+To deploy an email provider, you must create `provider.json` file under the `emails` directory of your Bitbucket repository. Example:
+
+__provider.json__
+```json
+{
+ "name": "smtp",
+ "enabled": true,
+ "credentials": {
+ "smtp_host": "smtp.server.com",
+ "smtp_port": 25,
+ "smtp_user": "smtp_user",
+ "smtp_pass": "smtp_secret_password"
+ }
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Emails/patch_provider) for more info on allowed attributes for Email Provider.
+
+### Deploy Email Templates
+
+The supported email templates are:
+- `verify_email`
+- `reset_email`
+- `welcome_email`
+- `blocked_account`
+- `stolen_credentials`
+- `enrollment_email`
+- `mfa_oob_code`
+
+To deploy an email template, you must create an HTML file under the `emails` directory of your Bitbucket repository. For each HTML file, you need to create a JSON file (with the same name) with additional options for that template. For example, to deploy a `blocked_account` template, you would create two files:
+
+```text
+your-bitbucket-repo/emails/blocked_account.html
+your-bitbucket-repo/emails/blocked_account.json
+```
+
+__blocked_account.json__
+```json
+{
+ "template": "blocked_account",
+ "from": "",
+ "subject": "",
+ "resultUrl": "",
+ "syntax": "liquid",
+ "body": "./blocked_account.html",
+ "urlLifetimeInSeconds": 432000,
+ "enabled": true
+}
+```
+
+## Excluded records
+
+You can exclude the following records from the deployment process: `rules`, `clients`, `databases`, `connections` and `resourceServers`. If excluded, the records will not be modified by deployments.
+
+
+
+## Keywords Mapping
+
+Beginning with version **3.0.0**, you can use keywords mapping to manage your secrets and tenant-based environment variables.
+
+There are two ways to use the keyword mappings. You can either wrap the key using `@` symbols (e.g., `@@key@@`), or you can wrap the key using `#` symbols (e.g., `##key##`).
+
+ - If you use `@` symbols, your value will be converted from a JavaScript object or value to a JSON string.
+
+ - If you use `#` symbols, Auth0 will perform a literal replacement.
+
+This is useful for something like specifying different variables across your environments. For example, you could specify different JWT timeouts for your Development, QA/Testing, and Production environments.
+
+Refer to the snippets below for sample implementations:
+
+__Client.json__
+```json
+{
+ ...
+ "callbacks": [
+ "##ENVIRONMENT_URL##/auth/callback"
+ ],
+ "jwt_configuration": {
+ "lifetime_in_seconds": ##JWT_TIMEOUT##,
+ "secret_encoded": true
+ }
+ ...
+}
+```
+
+
## Track Deployments
diff --git a/articles/extensions/cloudwatch.md b/articles/extensions/cloudwatch.md
new file mode 100644
index 0000000000..c68d6e3624
--- /dev/null
+++ b/articles/extensions/cloudwatch.md
@@ -0,0 +1,69 @@
+---
+description: How to install and configure the Auth0 Logs to CloudWatch extension.
+topics:
+ - extensions
+ - cloudwatch
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+
+# Auth0 Logs to CloudWatch
+
+The **Auth0 Logs to CloudWatch** extension is a scheduled job that exports your Auth0 logs to [CloudWatch](https://aws.amazon.com/cloudwatch/). Amazon CloudWatch is a monitoring and management service built for developers, system operators, site reliability engineers (SRE), and IT managers.
+
+## Configure the Extension
+
+To install and configure this extension, click on the **Auth0 Logs to CloudWatch** box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the [Management Portal](${manage_url}). The **Install Extension** window pops open.
+
+At this point you should set the following configuration variables:
+
+| Parameter | Description |
+|:-----------------|:------------|
+| **Schedule** | The frequency with which logs should be exported. The schedule can be customized even further after creation. |
+| **BATCH_SIZE** | The amount of logs to be read on each execution. Maximun, and default, is `100`. |
+| **START_FROM** | The checkpoint ID of the log from where you want to start. |
+| **SLACK_INCOMING_WEBHOOK** | The Slack incoming webhook URL used to send relevant updates. |
+| **SLACK_SEND_SUCCESS** | Toggle for sending verbose notifications to Slack. |
+| **LOG_LEVEL** | The minimal log level of events that you would like sent to CloudWatch. |
+| **LOG_TYPES** | The events for which logs should be exported. |
+| **CLOUDWATCH_LOG_GROUP_NAME** Required | CloudWatch log group name, created in CloudWatch. |
+| **CLOUDWATCH_LOG_STREAM_NAME** Required | CloudWatch log stream name. |
+| **AWS_ACCESS_KEY_ID** Required | AWS access key ID |
+| **AWS_SECRET_KEY** Required | AWS secret key |
+| **AWS_REGION** Required | Your AWS region |
+
+### Required permissions
+
+Extension requires these AWS permissions in order to send logs to CloudWatch:
+- `logs:PutLogEvents`
+- `logs:DescribeLogStreams`
+
+Once you have provided this information, click the _Install_ button to finish installing the extension.
+
+<%= include('./_includes/_batch-size') %>
+
+## Use the Extension
+
+You can monitor activity by logging into the extension. There you can find reports on most recent runs. Reports contains amount of logs processed and errors, if any.
+
+## Replay Logs
+
+In the event of a CloudWatch failure or service interruption you can replay the logs starting from the failed log.
+
+To replay logs:
+
+1. Get the checkpoint ID of the failed log.
+2. Go to the Auth0 Logs to CloudWatch extension settings.
+3. Enter the checkpoint in the **START_FROM** field.
+4. Click the **Save** button to replay the failed logs.
+
+## Slack Integration
+
+To set up [Slack](https://slack.com/) integration, provide an [Incoming Webhook URL](https://api.slack.com/incoming-webhooks) to the **SLACK_INCOMING_WEBHOOK** field in the Auth0 Logs to CloudWatch [extension settings](${manage_url}/#/extensions).
+
+
+
+The extension sends failed transaction notifications to Slack with the checkpoint code displayed in the message. You can also enable verbose notifications by turning on the `SLACK_SEND_SUCCESS` setting.
+
+
diff --git a/articles/extensions/custom-social-extensions.md b/articles/extensions/custom-social-extensions.md
index f1170c6b98..436b0117c4 100644
--- a/articles/extensions/custom-social-extensions.md
+++ b/articles/extensions/custom-social-extensions.md
@@ -1,35 +1,38 @@
---
description: How to configure a Custom Social Connection to your Auth0 app.
toc: true
+topics:
+ - extensions
+ - custom-social-connections
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Extension: Custom Social Connections
-The Custom Social Connections extension allows you to easily manage multiple social connections.
+The Custom Social Connections extension allows you to manage multiple social connections easily.
-## Set Up a New Social Connection
+## Set Up a New Social Connection Extension
-To install the Custom Social Connection app, click on the **Custom Social Connections** box on the main [Extensions](${manage_url}/#/extensions) page of the Management Portal. You will be prompted to install the app.
-
+To install the Custom Social Connections extension, log in to the Dashboard and go to [Extensions](${manage_url}/#/extensions). Click the **Custom Social Connections** box. You will be prompted to install the app.
-At this point, you will see the app listed under the **Installed Extensions** tab.
+When the extension has been installed, you'll be redirected to a page that lists your extension under **Installed Extensions** tab.
-
+## Configure the Social Connection Extension settings
Once you have installed the app, you will need to configure it to work with whichever social providers you require. To do so, click on the **Custom Social Connections** link listed under **Installed Extensions**.
You will be asked to authorize the Custom Social Connections app. After you do so, the **New Connection** window will open.
-
+Click the slider next to the social provider(s) you want to set up. The slider will turn from grey to green, indicating that a connection to that provider exists.
-Click the slider next to the social provider you want to set up. The slider will turn from grey to green, indicating that a connection to that provider exists. For additional information on how each individual provider handles authentication, see that provider's documentation.
+For information on how each provider handles authentication, see that provider's documentation.
-### Configure the Social Connection Settings
+### Settings configuration
-The **New Connection** window contains two tabs: **Settings** and **Apps**:
-
-
+As soon as you enable a specific social connection, Auth0 displays a pop-up **New Connection** window that contains two tabs: **Settings** and **Apps**. You will need to update these tabs accordingly so that your connection works as expected.
#### New Connection: Settings
@@ -39,16 +42,16 @@ The Settings page is used to provide the information required to set up the soci
- __Client ID__: The provider's client ID;
- __Client Secret__: The provider's client secret;
- __Authorization URL__: The URL where the transaction begins and authorization occurs;
-- __Token URL__: The URL used to exchange the code generated from the information you provide for an access_token;
+- __Token URL__: The URL used to exchange the code generated from the information you provide for an Access Token;
- __Scope__: The scope parameters for which you want access rights;
- __Fetch User Profile Script__: The JS function that returns the user profile and associated information. It will be auto-generated with the appropriate fields depending on the chosen provider.
- __Custom Headers__: An optional JSON object that lets you provide custom headers to be included in the HTTP calls to the provider. Should be in the format of:
```
{
- "Header1" : "Value",
- "Header2" : "Value"
- // ...
+ "Header1" : "Value",
+ "Header2" : "Value"
+ // ...
}
```
@@ -58,18 +61,18 @@ After you have provided values for the required fields, click **Save**.
Once you have successfully configured the connection, you will be presented with a list of apps associated with your Auth0 tenant under the **Apps** tab of the **New Connection** window.
-Using the slider, enable this social connection for the apps that you want to use it with.
+Using the slider, enable this social connection for the apps that you want to use it with. **If you do not enable *any* of the listed apps, you will not be able to use the connection.**
Once you have enabled/disabled the appropriate apps, click **Save**.
### Provide your Callback URL to the Identity Provider
-The callback URL is the URL that is invoked by the provider after the authentication request has finished.
+The callback URL is the URL that is invoked by the provider after the authentication request has finished. Your provider will ask you to provide this URL at some point during the setup process.
Use this value for the **Callback URL**:
`https://${account.namespace}/login/callback`
-Depending on the provider, this field can be referred to by different names. Sometimes called a **Redirect URI** the callback URL may also be be referred to as: "Valid OAuth redirect URI", "Authorized redirect URI", "Allowed Return URL" or something similar.
+Depending on the provider, this field can be referred to by different names. Sometimes called a **Redirect URI**, the callback URL may also be referred to as: "Valid OAuth redirect URI," "Authorized redirect URI," "Allowed Return URL," or something similar.
## Use your new connection
@@ -85,13 +88,13 @@ Lock does not currently support displaying buttons for custom social connections
## Optional: Set up Basic Authentication
-By default, when invoking the __Token URL__ to exchange the authentication code for an access_token, Auth0 will provide the `client ID` and `client secret` as part of the body of the POST. Some identity providers require [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication), which involves providing those same credentials in a HTTP header.
+By default, when invoking the __Token URL__ to exchange the authentication code for an Access Token, Auth0 will provide the `client ID` and `client secret` as part of the body of the POST. Some identity providers require [HTTP Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication), which involves providing those same credentials in an HTTP header.
-If the identity provider requires Basic Authentication, you can be use the __Custom Headers__ setting with a JSON object like this:
+If the identity provider requires Basic Authentication, you can use the __Custom Headers__ setting with a JSON object like this:
```
{
- "Authorization" : "Basic xxxxxxxx"
+ "Authorization" : "Basic xxxxxxxx"
}
```
@@ -99,14 +102,10 @@ If the identity provider requires Basic Authentication, you can be use the __Cus
```
{
- "Authorization" : "Basic MTIzNDU2OmFiY2RlZg=="
+ "Authorization" : "Basic MTIzNDU2OmFiY2RlZg=="
}
```
## Additional Steps
-Depending on which social providers you are you using, there may be additional steps in the provider configuration to enable the connection.
-
-### WordPress
-
-You will need to add the associated **Plugin** in WordPress for the social connection. For example, to enable login with Slack the Slack plugin will need to be enabled in WordPress (make sure you’re logged in as an Administrator).
\ No newline at end of file
+Depending on which social providers you are you using, there may be additional steps in the provider configuration to enable the connection. Please refer to the provider-specific documentation for clarifying details.
diff --git a/articles/extensions/delegated-admin/hooks.md b/articles/extensions/delegated-admin/hooks.md
deleted file mode 100644
index 9cc6360457..0000000000
--- a/articles/extensions/delegated-admin/hooks.md
+++ /dev/null
@@ -1,319 +0,0 @@
----
-description: How to customize the behavior of the Delegated Administration extension using Hooks
-toc: true
----
-
-# Delegated Administration: Hooks
-
-If you are a user with the `Delegated Admin - Administrator` role in your User Profile, log in to the Delegated Administration Dashboard, and click on your name in the top right corner, you'll see a *Configure* option. On the Configuration page, you can manage the different Hooks and queries that allow you to customize the behavior of the Delegated Administration extension.
-
-
-
-## Hooks Signature
-
-Hooks always have the following signature:
-
-```js
-function(ctx, callback) {
- // First do some work
- ...
-
- // Done
- return callback(null, something);
-}
-```
-
-The context object will expose a few helpers and information about the current request. The following methods and properties are available in every Hook.
-
-**1. Logging**
-
- To add a message to the Webtask logs (which you can view using the [Realtime Webtask Logs](/extensions/realtime-webtask-logs) extension), call the `log` method:
-
- ```js
- ctx.log('Hello there', someValue, otherValue);
- ```
-
-**2. Caching**
-
- To cache something (such as a long list of departments), you can store it on the context's `global` object. This object will be available until the Webtask container recycles.
-
- ```js
- ctx.global.departments = [ 'IT', 'HR', 'Finance' ];
- ```
-
-**3. Custom Data**
-
- You can store custom data within the extension. This is field is limited to 400kb of data.
-
- ```js
- var data = {
- departments: [ 'IT', 'HR', 'Finance' ]
- };
-
- ctx.write(data)
- .then(function() {
- ...
- })
- .catch(function(err) {
- ...
- });
- ```
-
- To read the data:
-
- ```js
- ctx.read()
- .then(function(data) {
- ...
- })
- .catch(function(err) {
- ...
- });
- ```
-
-**4. Payload and Request**
-
- Each Hook exposes the current payload and/or request with specific information. The request will always contain information about the user that is logged into the Users Dashboard:
-
- ```js
- var currentUser = ctx.request.user;
- ```
-
-**5. Remote Calls**
-
- If you want to call an external service (such as an API) to validate data or to load memberships, you can do this using the `request` module.
-
- ```js
- function(ctx, callback) {
- var request = require('request');
- request('http://api.mycompany.com/departments', function (error, response, body) {
- if (error) {
- return callback(error);
- }
-
- ...
- });
- }
- ```
-
-## The Filter Hook
-
-By default, users with the **Delegated Admin - User** role see *all* users associated with the Auth0 account. However, you can filter the data users see using the **Filter Hook**.
-
-### The Hook contract:
-
- - `ctx`: The context object
- - `callback(error, query)`: The callback to which you can return an error or the [lucene query](/api/management/v2/query-string-syntax) used when filtering the users. The extension will send this query to the [`GET Users` endpoint](/api/management/v2#!/Users/get_users) of the Management API
-
-### Example
-
-If **Kelly** manages the Finance department, she should only see the users that are also part of the Finance department. We'll filter the users with respect to the department of the current user.
-
-```js
-function(ctx, callback) {
- // Get the department from the current user's metadata.
- var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
- if (!department || !department.length) {
- return callback(new Error('The current user is not part of any department.'));
- }
-
- // The IT department can see all users.
- if (department === 'IT') {
- return callback();
- }
-
- // Return the lucene query.
- return callback(null, 'app_metadata.department:"' + department + '"');
-}
-```
-
-::: panel-warning Using Special Characters
-Do not use single quotes, double quotes, or any other special characters (such as `+` or `-`) in any term on which you'll want to filter. This might cause issues with the Lucene query.
-:::
-
-If you do not configure this Hook, the search returns **all users**.
-
-## The Access Hook
-
-While the **Filter Hook** only applies filtering logic you'll need a second layer of logic to determine if the current user is allowed to access a specific user. This is what the **Access Hook** allows you to do, determine if the current user is allowed to read, delete, block, or unblock a specific user.
-
-### The Hook contract:
-
- - `ctx`: The context object
- - `payload`: The payload object
- - `action`: The current action (eg: `delete:user`) that is being executed
- - `user`: The user on which the action is being executed
- - `callback(error)`: The callback to which you can return an error if access is denied
-
-Example: **Kelly** manages the Finance department and she should only be able to access users within her department.
-
-```js
-function(ctx, callback) {
- if (ctx.payload.action === 'delete:user') {
- return callback(new Error('You are not allowed to delete users.'));
- }
-
- // Get the department from the current user's metadata.
- var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
- if (!department || !department.length) {
- return callback(new Error('The current user is not part of any department.'));
- }
-
- // The IT department can access all users.
- if (department === 'IT') {
- return callback();
- }
-
- ctx.log('Verifying access:', ctx.payload.user.app_metadata.department, department);
-
- if (!ctx.payload.user.app_metadata.department || ctx.payload.user.app_metadata.department !== department) {
- return callback(new Error('You can only access users within your own department.'));
- }
-
- return callback();
-}
-```
-
-If this hook is not configured all users will be accessible.
-
-Supported action names:
-
- - `read:user`
- - `delete:user`
- - `reset:password`
- - `change:password`
- - `change:username`
- - `change:email`
- - `read:devices`
- - `read:logs`
- - `remove:multifactor-provider`
- - `block:user`
- - `unblock:user`
- - `send:verification-email`
-
-#### Create Hook
-
-Whenever new users are created you'll want these users to be assigned to the group/department/vendor/... of the current user. This is what the **Create Hook** allows you to configure.
-
-Hook contract:
-
- - `ctx`: The context object.
- - `payload`: The payload object.
- - `memberships`: An array of memberships that were selected in the UI when creating the user.
- - `email`: The email address of the user.
- - `password`: The password of the user.
- - `connection`: The name of the user.
- - `callback(error, user)`: The callback to which you can return an error and the user object that should be sent to the Management API.
-
-Example: **Kelly** manages the Finance department. When she creates users, these users should be assigned to her department.
-
-```js
-function(ctx, callback) {
- if (!ctx.payload.memberships || ctx.payload.memberships.length === 0) {
- return callback(new Error('The user must be created within a department.'));
- }
-
- // Get the department from the current user's metadata.
- var currentDepartment = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
- if (!currentDepartment || !currentDepartment.length) {
- return callback(new Error('The current user is not part of any department.'));
- }
-
- // If you're not in the IT department, you can only create users within your own department.
- // IT can create users in all departments.
- if (currentDepartment !== 'IT' && ctx.payload.memberships[0] !== currentDepartment) {
- return callback(new Error('You can only create users within your own department.'));
- }
-
- // This is the payload that will be sent to API v2. You have full control over how the user is created in API v2.
- return callback(null, {
- email: ctx.payload.email,
- password: ctx.payload.password,
- connection: ctx.payload.connection,
- app_metadata: {
- department: ctx.payload.memberships[0]
- }
- });
-}
-```
-
-::: warning
-Auth0 only supports user creation with Database Connections.
-:::
-
-## The Memberships Query Hook
-
-When creating a new user, the UI shows a drop-down where you can choose the membership(s) you want assigned to a user. These memberships are then defined using the **Memberships Query**.
-
-### The Hook contract:
-
- - `ctx`: The context object
- - `callback(error, { createMemberships: true/false, memberships: [ ...] })`: The callback to which you can return an error and an object containing the membership configuration
-
-Example: Users of the IT department should be able to create users in other departments. Users from other departments should only be able to create users for their own departments.
-
-```js
-function(ctx, callback) {
- var currentDepartment = ctx.payload.user.app_metadata.department;
- if (!currentDepartment || !currentDepartment.length) {
- return callback(null, [ ]);
- }
-
- if (currentDepartment === 'IT') {
- return callback(null, [ 'IT', 'HR', 'Finance', 'Marketing' ]);
- }
-
- return callback(null, [ ctx.payload.user.app_metadata.department ]);
-}
-```
-
-**Notes**:
-
-* Because you can only use this query in the UI, you'll need to assign memberships using the *Create Users* function if you need to enforce the assigning of users to specific departments.
-* If there is only one membership possible, this field will not show in the UI.
-
-You can allow the end user to enter any value `memberships` by setting `createMemberships` to true.
-
-```js
-function(ctx, callback) {
- var currentDepartment = ctx.payload.user.app_metadata.department;
- if (!currentDepartment || !currentDepartment.length) {
- return callback(null, [ ]);
- }
-
- return callback(null, {
- createMemberships: ctx.payload.user.app_metadata.department === 'IT' ? true : false,
- memberships: [ ctx.payload.user.app_metadata.department ]
- });
-}
-```
-
-## The Settings Query Hook
-
-The **Settings Query** allows you to customize the look and feel of the extension.
-
-### The Hook contract
-
- - `ctx`: The context object
- - `callback(error, settings)`: The callback to which you can return an error and a settings object
-
-Example:
-
-```js
-function(ctx, callback) {
- var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
-
- return callback(null, {
- // Only these connections should be visible in the connections picker.
- // If only one connection is available, the connections picker will not be shown in the UI.
- connections: [ 'Username-Password-Authentication', 'My-Custom-DB' ],
- // The dictionary allows you to overwrite the title of the dashboard and the "Memberships" label in the Create User dialog.
- dict: {
- title: department ? department + ' User Management' : 'User Management Dashboard',
- memberships: 'Departments'
- },
- // The CSS option allows you to inject a custom CSS file depending on the context of the current user (eg: a different CSS for every customer)
- css: (department && department !== 'IT') && 'https://rawgit.com/auth0-extensions/auth0-delegated-administration-extension/master/docs/theme/fabrikam.css'
- });
-}
-```
diff --git a/articles/extensions/delegated-admin/index.md b/articles/extensions/delegated-admin/index.md
deleted file mode 100644
index 995602bc43..0000000000
--- a/articles/extensions/delegated-admin/index.md
+++ /dev/null
@@ -1,173 +0,0 @@
----
-description: The Delegated Administration extension allows you to expose the Users dashboard to a group of users, without allowing them access to the dashboard.
-url: /extensions/delegated-admin
-toc: true
----
-
-# Delegated Administration
-
-The **Delegated Administration** extension allows you to grant a select group of people administrative permissions to the [Users page](${manage_url}/#/users) without providing access to any other area. This is done by exposing the [Users Dashboard](${manage_url}/#/users) as an Auth0 application.
-
-:::panel PSaaS Appliance Availability
-The Delegated Administration extension is available for [PSaaS Appliance](/appliance) customers who are running build `10755` or later, and have User Search enabled.
-:::
-
-Prior to configuring the extension, you will need to:
-
-* [Create and configure an Auth0 Application](#create-an-application)
-* [Enable a Connection on the Application](#enable-a-connection-on-the-application)
-* [Add a user to the Connection](#add-a-user-to-the-new-connection)
-
-## Create an Application
-
-The first step is to create the Application that the extension exposes to those who should have administrative privileges to the Users page.
-
-After you've logged into the [Management Dashboard](${manage_url}), navigate to [Applications](${manage_url}/#/applications) and click on **+Create Application**. Provide a name for your Application (such as `Users Dashboard`) and set the Application type to `Single Page Web Applications`. Click **Create** to proceed.
-
-
-
-### Configure Application Settings
-
-Once you've created your Application, you'll need to make the following Application configuration changes.
-
-Click on the **Settings** tab and set the **Allowed Callback URLs**. This varies based on your location:
-
-| Location | Allowed Callback URL |
-| --- | --- |
-| USA | `https://${account.tenant}.us.webtask.io/auth0-delegated-admin/login` |
-| Europe | `https://${account.tenant}.eu.webtask.io/auth0-delegated-admin/login` |
-| Australia | `https://${account.tenant}.au.webtask.io/auth0-delegated-admin/login` |
-
-You will also need to configure the **Allowed Logout URLs**:
-
-| Location | Allowed Logout URL |
-| --- | --- |
-| USA | `https://${account.tenant}.us.webtask.io/auth0-delegated-admin` |
-| Europe | `https://${account.tenant}.eu.webtask.io/auth0-delegated-admin` |
-| Australia | `https://${account.tenant}.au.webtask.io/auth0-delegated-admin` |
-
-Copy the **Client ID** value.
-
-Navigate to **Settings > Show Advanced Settings > OAuth** and paste the **Client ID** value to the **Allowed APPs / APIs** field.
-
-Next, set the **JsonWebToken Signature Algorithm** to `RS256`, and make sure the **OIDC Conformant** toggle is disabled.
-
-::: note
-The **Delegated Administration** extension requires applications to disable the **OIDC Conformant** flag. After turning off **OIDC Conformant** on the dashboard, ensure your application's authentication code is updated as well.
-:::
-
-
-
-Click **Save Changes** to proceed.
-
-### Enable a Connection on the Application
-
-When you create a new Application, Auth0 enables all [Connections](/identityproviders) associated with your tenant by default. For the purposes of this tutorial, we will disable all Connections (this helps keep our Application secure, since no one can add themselves using one of our existing Connections), create a new Database Connection, and enable only the newly-created Database Connection. However, you can choose to use any type of Connection.
-
-#### Disable All Existing Connections
-
-Switch over to the Application's **Connections** tab and disable all the Connections using the associated switches.
-
-#### Create a New Connection
-
-In the navigation pane of the Management Dashboard, click on **Connections** > [Database Connections](${manage_url}/#/connections/database).
-
-On the Database Connections page, click on **+Create DB Connection**. Provide a name for your Connection, such as `Helpdesk`.
-
-Click **Save** to proceed.
-
-
-
-Navigate to the **Settings** tab of your new Connection and enable the **Disable Sign Ups** option. For security reasons, this ensures that even users who have the link to our Connection cannot sign themselves up.
-
-
-
-Under the **Applications Using This Connection** section, enable this Connection for your `Users Dashboard` Application.
-
-### Add a User to the New Connection
-
-You will need to add at least one user to your Connection. You can do this via the [Users page](${manage_url}/#/users), where you can specify the Connection for the user during the configuration process.
-
-### Assign Roles to Users
-
-Auth0 grants the user(s) in your Connection access to the Delegated Administration extension based on their roles:
-
-- **Delegated Admin - User**: Grants permission to search for users, create users, open users and execute actions on these users (such as `delete`, `block`, and so on);
-
-- **Delegated Admin - Administrator**: In addition to all of the rights a user has, administrators can see all logs in the tenant and configure Hooks.
-
-To use the extension, users must have either of these roles defined in one of the following fields of their user profiles:
-
-* `user.roles`
-* `user.app_metadata.roles`
-* `user.app_metadata.authorization.roles`
-
-You can set these fields manually or via [rules](/rules).
-
-#### Set User Roles via Rules
-
-This rule gives users from the `IT Department` the `Delegated Admin - Administrator` role and users from `Department Managers` are the `Delegated Admin - User` role.
-
-```js
-function (user, context, callback) {
- if (context.clientID === 'CLIENT_ID') {
- if (user.groups && user.groups.indexOf('IT Department') > -1) {
- user.roles = user.roles || [ ];
- user.roles.push('Delegated Admin - Administrator');
- return callback(null, user, context);
- } else if (user.app_metadata && user.app_metadata.isDepartmentManager && user.app_metadata.department && user.app_metadata.department.length) {
- user.roles = user.roles || [ ];
- user.roles.push('Delegated Admin - User');
- return callback(null, user, context);
- }
-
- return callback(new UnauthorizedError('You are not allowed to use this application.'));
- }
-
- callback(null, user, context);
-}
-```
-
-## Install the Extension
-
-Now that we've created and configured an Application, a Connection, and our users, we can install and configure the extension itself.
-
-On the Management Dashboard, navigate to the [Extensions](${manage_url}/#/extensions) page. Click on the **Delegated Administration** box in the list of provided extensions. The **Install Extension** window will open.
-
-
-
-Set the following configuration variables:
-
-- **EXTENSION_CLIENT_ID**: The **Client ID** value of the Application you will use. You can find this value on the **Settings** page of your Application.
-
-- **TITLE** (optional): Set a title for your Application. It will be displayed at the header of the page.
-
-- **CUSTOM_CSS** (optional): Provide a CSS script to customize the look and feel of your Application.
-
-Once done, click **Install**. Your extension is now ready to use!
-
-If you navigate back to the [Applications](${manage_url}/#/applications) view, you will see that the extension automatically created an additional application called `auth0-delegated-admin`.
-
-
-
-Because the application is authorized to access the [Management API](/api/management/v2), you shouldn't modify it.
-
-## Use the Extension
-
-To access your newly created users dashboard, navigate to [**Extensions**](${manage_url}/#/extensions) > **Installed Extensions** > **Delegated Administration Dashboard**.
-
-A new tab will open to display the login prompt.
-
-
-
-Because we disabled signups for this Connection during the configuration period, the login screen doesn't display a Sign Up option.
-
-Once you provide valid credentials, you'll be redirected to the *Delegated Administration Dashboard*.
-
-
-
-## Keep Reading
-
-* [Customizing the Delegated Administration Extension Using Hooks](/extensions/delegated-admin/hooks)
-
-* [Managing Users in the Delegated Administration Extension Dashboard](/extensions/delegated-admin/manage-users)
diff --git a/articles/extensions/delegated-admin/index.yml b/articles/extensions/delegated-admin/index.yml
new file mode 100644
index 0000000000..96e0fc8807
--- /dev/null
+++ b/articles/extensions/delegated-admin/index.yml
@@ -0,0 +1,9 @@
+versioning:
+ baseUrl: extensions/delegated-admin
+ current: v3
+ versions:
+ - v2
+ - v3
+ defaultArticles:
+ v2: index
+ v3: index
\ No newline at end of file
diff --git a/articles/extensions/delegated-admin/manage-users.md b/articles/extensions/delegated-admin/manage-users.md
deleted file mode 100644
index e5f1cbf662..0000000000
--- a/articles/extensions/delegated-admin/manage-users.md
+++ /dev/null
@@ -1,89 +0,0 @@
----
-description: How to manage users in the Delegated Administration extension
-toc: true
----
-
-# Delegated Administration: Manage Users
-
-In the Application exposed by the Delegated Administration extension, there are two views available: *Users* and *Logs*. On the *Users* view, you can see the display and modify users associated with your Auth0 account.
-
-By default, all users are displayed, but you can filter the displayed list by configuring a [filter hook](/extensions/delegated-admin/hooks#the-filter-hook).
-
-## Available User Actions in the Delegated Administration Dashboard
-
-The table below lists the options you can perform on users, as well as information on whether the option is available via the [Management Dashboard](${manage_url}/#/) and/or the Delegated Administration extension. To limit the number of options someone with access to the Dashboard exposed by the Delegated Administration extension, configure an [access hook](#access-hook).
-
-
-
-
-
Action
-
Available in the Management Dashboard
-
Available in the Delegated Administration Extension
-
-
-
Create User
-
Yes
-
Yes
-
-
-
Contact User
-
Yes
-
No
-
-
-
Sign in as User (Impersonation)
-
Yes
-
No
-
-
-
Block User
-
Yes
-
Yes
-
-
-
Delete User
-
Yes
-
Yes
-
-
-
Send Verification Email
-
Yes
-
Yes
-
-
-
Change Email
-
Yes
-
Yes
-
-
-
Change Password
-
Yes
-
Yes
-
-
-
Reset Password
-
No
-
Yes
-
-
-
-
-Notice the new *Reset Password* option available via the extension. This option will send an email to the user allowing them to choose a new password. To do this click on a user and select *Actions > Reset Password*.
-
-
-
-This will send an email to the user, containing a link to change the password.
-
-If your profile indicates that you have the `Delegated Admin - Administrator` role, the *Logs* view allows you to see a list of authentications made by your users (this tab is only visible to users with the `Delegated Admin - Administrator` role). The contents of this view are a subset of the data displayed in the [Logs Dashboard](${manage_url}/#/logs). The Log Dashboard also displays data on administrative actions taken in the Dashboard.
-
-## Create Users
-
-You can create a new user by selecting the **+ Create User** button on the *Users* view. You need to specify are email and password. Depending on your role, you may not be able to set the *Department* to which the new user belongs.
-
-For example, users with the `Delegated Admin - Administrator` role can see the **Department** field and select any of its values.
-
-
-
-On the other hand, Kelly who has the `Delegated Admin - User` role and belongs to the Finance department cannot see this field. The user she creates will be automatically assigned to the Finance department.
-
-
diff --git a/articles/extensions/delegated-admin/v2/hooks.md b/articles/extensions/delegated-admin/v2/hooks.md
new file mode 100644
index 0000000000..b9a7b57ce6
--- /dev/null
+++ b/articles/extensions/delegated-admin/v2/hooks.md
@@ -0,0 +1,323 @@
+---
+description: How to customize the behavior of the Delegated Administration extension using Hooks
+toc: true
+topics:
+ - extensions
+ - delegated-admin
+ - hooks
+---
+
+# Delegated Administration: Hooks
+
+If you are a user with the `Delegated Admin - Administrator` role in your User Profile, log in to the Delegated Administration Dashboard, and click on your name in the top right corner, you'll see a *Configure* option. On the Configuration page, you can manage the different Hooks and queries that allow you to customize the behavior of the Delegated Administration extension.
+
+
+
+## Hooks Signature
+
+Hooks always have the following signature:
+
+```js
+function(ctx, callback) {
+ // First do some work
+ ...
+
+ // Done
+ return callback(null, something);
+}
+```
+
+The context object will expose a few helpers and information about the current request. The following methods and properties are available in every Hook.
+
+**1. Logging**
+
+ To add a message to the Webtask logs (which you can view using the [Realtime Webtask Logs](/extensions/realtime-webtask-logs) extension), call the `log` method:
+
+ ```js
+ ctx.log('Hello there', someValue, otherValue);
+ ```
+
+**2. Caching**
+
+ To cache something (such as a long list of departments), you can store it on the context's `global` object. This object will be available until the Webtask container recycles.
+
+ ```js
+ ctx.global.departments = [ 'IT', 'HR', 'Finance' ];
+ ```
+
+**3. Custom Data**
+
+ You can store custom data within the extension. This is field is limited to 400kb of data.
+
+ ```js
+ var data = {
+ departments: [ 'IT', 'HR', 'Finance' ]
+ };
+
+ ctx.write(data)
+ .then(function() {
+ ...
+ })
+ .catch(function(err) {
+ ...
+ });
+ ```
+
+ To read the data:
+
+ ```js
+ ctx.read()
+ .then(function(data) {
+ ...
+ })
+ .catch(function(err) {
+ ...
+ });
+ ```
+
+**4. Payload and Request**
+
+ Each Hook exposes the current payload and/or request with specific information. The request will always contain information about the user that is logged into the Users Dashboard:
+
+ ```js
+ var currentUser = ctx.request.user;
+ ```
+
+**5. Remote Calls**
+
+ If you want to call an external service (such as an API) to validate data or to load memberships, you can do this using the `request` module.
+
+ ```js
+ function(ctx, callback) {
+ var request = require('request');
+ request('http://api.mycompany.com/departments', function (error, response, body) {
+ if (error) {
+ return callback(error);
+ }
+
+ ...
+ });
+ }
+ ```
+
+## The Filter Hook
+
+By default, users with the **Delegated Admin - User** role see *all* users associated with the Auth0 account. However, you can filter the data users see using the **Filter Hook**.
+
+### The Hook contract:
+
+ - `ctx`: The context object
+ - `callback(error, query)`: The callback to which you can return an error or the [lucene query](/api/management/v2/query-string-syntax) used when filtering the users. The extension will send this query to the [`GET Users` endpoint](/api/management/v2#!/Users/get_users) of the Management API
+
+### Example
+
+If **Kelly** manages the Finance department, she should only see the users that are also part of the Finance department. We'll filter the users with respect to the department of the current user.
+
+```js
+function(ctx, callback) {
+ // Get the department from the current user's metadata.
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+ if (!department || !department.length) {
+ return callback(new Error('The current user is not part of any department.'));
+ }
+
+ // The IT department can see all users.
+ if (department === 'IT') {
+ return callback();
+ }
+
+ // Return the lucene query.
+ return callback(null, 'app_metadata.department:"' + department + '"');
+}
+```
+
+::: panel-warning Using Special Characters
+Do not use single quotes, double quotes, or any other special characters (such as `+` or `-`) in any term on which you'll want to filter. This might cause issues with the Lucene query.
+:::
+
+If you do not configure this Hook, the search returns **all users**.
+
+## The Access Hook
+
+While the **Filter Hook** only applies filtering logic you'll need a second layer of logic to determine if the current user is allowed to access a specific user. This is what the **Access Hook** allows you to do, determine if the current user is allowed to read, delete, block, or unblock a specific user.
+
+### The Hook contract:
+
+ - `ctx`: The context object
+ - `payload`: The payload object
+ - `action`: The current action (eg: `delete:user`) that is being executed
+ - `user`: The user on which the action is being executed
+ - `callback(error)`: The callback to which you can return an error if access is denied
+
+Example: **Kelly** manages the Finance department and she should only be able to access users within her department.
+
+```js
+function(ctx, callback) {
+ if (ctx.payload.action === 'delete:user') {
+ return callback(new Error('You are not allowed to delete users.'));
+ }
+
+ // Get the department from the current user's metadata.
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+ if (!department || !department.length) {
+ return callback(new Error('The current user is not part of any department.'));
+ }
+
+ // The IT department can access all users.
+ if (department === 'IT') {
+ return callback();
+ }
+
+ ctx.log('Verifying access:', ctx.payload.user.app_metadata.department, department);
+
+ if (!ctx.payload.user.app_metadata.department || ctx.payload.user.app_metadata.department !== department) {
+ return callback(new Error('You can only access users within your own department.'));
+ }
+
+ return callback();
+}
+```
+
+If this hook is not configured all users will be accessible.
+
+Supported action names:
+
+ - `read:user`
+ - `delete:user`
+ - `reset:password`
+ - `change:password`
+ - `change:username`
+ - `change:email`
+ - `read:devices`
+ - `read:logs`
+ - `remove:multifactor-provider`
+ - `block:user`
+ - `unblock:user`
+ - `send:verification-email`
+
+#### Create Hook
+
+Whenever new users are created you'll want these users to be assigned to the group/department/vendor/... of the current user. This is what the **Create Hook** allows you to configure.
+
+Hook contract:
+
+ - `ctx`: The context object.
+ - `payload`: The payload object.
+ - `memberships`: An array of memberships that were selected in the UI when creating the user.
+ - `email`: The email address of the user.
+ - `password`: The password of the user.
+ - `connection`: The name of the user.
+ - `callback(error, user)`: The callback to which you can return an error and the user object that should be sent to the Management API.
+
+Example: **Kelly** manages the Finance department. When she creates users, these users should be assigned to her department.
+
+```js
+function(ctx, callback) {
+ if (!ctx.payload.memberships || ctx.payload.memberships.length === 0) {
+ return callback(new Error('The user must be created within a department.'));
+ }
+
+ // Get the department from the current user's metadata.
+ var currentDepartment = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+ if (!currentDepartment || !currentDepartment.length) {
+ return callback(new Error('The current user is not part of any department.'));
+ }
+
+ // If you're not in the IT department, you can only create users within your own department.
+ // IT can create users in all departments.
+ if (currentDepartment !== 'IT' && ctx.payload.memberships[0] !== currentDepartment) {
+ return callback(new Error('You can only create users within your own department.'));
+ }
+
+ // This is the payload that will be sent to API v2. You have full control over how the user is created in API v2.
+ return callback(null, {
+ email: ctx.payload.email,
+ password: ctx.payload.password,
+ connection: ctx.payload.connection,
+ app_metadata: {
+ department: ctx.payload.memberships[0]
+ }
+ });
+}
+```
+
+::: warning
+Auth0 only supports user creation with Database Connections.
+:::
+
+## The Memberships Query Hook
+
+When creating a new user, the UI shows a drop-down where you can choose the membership(s) you want assigned to a user. These memberships are then defined using the **Memberships Query**.
+
+### The Hook contract:
+
+ - `ctx`: The context object
+ - `callback(error, { createMemberships: true/false, memberships: [ ...] })`: The callback to which you can return an error and an object containing the membership configuration
+
+Example: Users of the IT department should be able to create users in other departments. Users from other departments should only be able to create users for their own departments.
+
+```js
+function(ctx, callback) {
+ var currentDepartment = ctx.payload.user.app_metadata.department;
+ if (!currentDepartment || !currentDepartment.length) {
+ return callback(null, [ ]);
+ }
+
+ if (currentDepartment === 'IT') {
+ return callback(null, [ 'IT', 'HR', 'Finance', 'Marketing' ]);
+ }
+
+ return callback(null, [ ctx.payload.user.app_metadata.department ]);
+}
+```
+
+**Notes**:
+
+* Because you can only use this query in the UI, you'll need to assign memberships using the *Create Users* function if you need to enforce the assigning of users to specific departments.
+* If there is only one membership possible, this field will not show in the UI.
+
+You can allow the end user to enter any value `memberships` by setting `createMemberships` to true.
+
+```js
+function(ctx, callback) {
+ var currentDepartment = ctx.payload.user.app_metadata.department;
+ if (!currentDepartment || !currentDepartment.length) {
+ return callback(null, [ ]);
+ }
+
+ return callback(null, {
+ createMemberships: ctx.payload.user.app_metadata.department === 'IT' ? true : false,
+ memberships: [ ctx.payload.user.app_metadata.department ]
+ });
+}
+```
+
+## The Settings Query Hook
+
+The **Settings Query** allows you to customize the look and feel of the extension.
+
+### The Hook contract
+
+ - `ctx`: The context object
+ - `callback(error, settings)`: The callback to which you can return an error and a settings object
+
+Example:
+
+```js
+function(ctx, callback) {
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+
+ return callback(null, {
+ // Only these connections should be visible in the connections picker.
+ // If only one connection is available, the connections picker will not be shown in the UI.
+ connections: [ 'Username-Password-Authentication', 'My-Custom-DB' ],
+ // The dictionary allows you to overwrite the title of the dashboard and the "Memberships" label in the Create User dialog.
+ dict: {
+ title: department ? department + ' User Management' : 'User Management Dashboard',
+ memberships: 'Departments'
+ },
+ // The CSS option allows you to inject a custom CSS file depending on the context of the current user (eg: a different CSS for every customer)
+ css: (department && department !== 'IT') && 'https://rawgit.com/auth0-extensions/auth0-delegated-administration-extension/master/docs/theme/fabrikam.css'
+ });
+}
+```
diff --git a/articles/extensions/delegated-admin/v2/index.md b/articles/extensions/delegated-admin/v2/index.md
new file mode 100644
index 0000000000..79818e9038
--- /dev/null
+++ b/articles/extensions/delegated-admin/v2/index.md
@@ -0,0 +1,196 @@
+---
+description: The Delegated Administration extension allows you to expose the Users dashboard to a group of users, without allowing them access to the dashboard.
+toc: true
+topics:
+ - extensions
+ - delegated-admin
+contentType:
+ - how-to
+ - concept
+ - index
+useCase: extensibility-extensions
+---
+
+# Delegated Administration
+
+The **Delegated Administration** extension allows you to grant a select group of people administrative permissions to the [Users page](${manage_url}/#/users) without providing access to any other area. This is done by exposing the [Users Dashboard](${manage_url}/#/users) as an Auth0 application.
+
+Prior to configuring the extension, you will need to:
+
+* [Create and configure an Auth0 Application](#create-an-application)
+* [Enable a Connection on the Application](#enable-a-connection-on-the-application)
+* [Add a user to the Connection](#add-a-user-to-the-new-connection)
+
+## Create an Application
+
+The first step is to create the Application that the extension exposes to those who should have administrative privileges to the Users page.
+
+After you've logged into the [Management Dashboard](${manage_url}), navigate to [Applications](${manage_url}/#/applications) and click on **+Create Application**. Provide a name for your Application (such as `Users Dashboard`) and set the Application type to `Single-Page Web Applications`. Click **Create** to proceed.
+
+
+
+### Configure Application Settings
+
+Once you've created your Application, you'll need to make the following Application configuration changes.
+
+Click on the **Settings** tab and set the **Allowed Callback URLs**. This varies based on your location:
+
+If you are using Node 8:
+
+| Location | Allowed Callback URL |
+| --- | --- |
+| USA | `https://${account.tenant}.us8.webtask.io/auth0-delegated-admin/login` |
+| Europe | `https://${account.tenant}.eu8.webtask.io/auth0-delegated-admin/login` |
+| Australia | `https://${account.tenant}.au8.webtask.io/auth0-delegated-admin/login` |
+
+If you are using Node 12:
+
+| Location | Allowed Callback URL |
+| --- | --- |
+| USA | `https://${account.tenant}.us12.webtask.io/auth0-delegated-admin/login` |
+| Europe | `https://${account.tenant}.eu12.webtask.io/auth0-delegated-admin/login` |
+| Australia | `https://${account.tenant}.au12.webtask.io/auth0-delegated-admin/login` |
+
+You will also need to configure the **Allowed Logout URLs**:
+
+If you are using Node 8:
+
+| Location | Allowed Logout URL |
+| --- | --- |
+| USA | `https://${account.tenant}.us8.webtask.io/auth0-delegated-admin` |
+| Europe | `https://${account.tenant}.eu8.webtask.io/auth0-delegated-admin` |
+| Australia | `https://${account.tenant}.au8.webtask.io/auth0-delegated-admin` |
+
+If you are using Node 12:
+
+| Location | Allowed Logout URL |
+| --- | --- |
+| USA | `https://${account.tenant}.us12.webtask.io/auth0-delegated-admin` |
+| Europe | `https://${account.tenant}.eu12.webtask.io/auth0-delegated-admin` |
+| Australia | `https://${account.tenant}.au12.webtask.io/auth0-delegated-admin` |
+
+Copy the **Client ID** value.
+
+Navigate to **Settings > Show Advanced Settings > OAuth** and paste the **Client ID** value to the **Allowed APPs / APIs** field.
+
+Next, set the **JsonWebToken Signature Algorithm** to `RS256`, and make sure the **OIDC Conformant** toggle is disabled.
+
+::: note
+The **Delegated Administration** extension requires applications to disable the **OIDC Conformant** flag. After turning off **OIDC Conformant** on the dashboard, ensure your application's authentication code is updated as well.
+:::
+
+
+
+Click **Save Changes** to proceed.
+
+### Enable a Connection on the Application
+
+When you create a new Application, Auth0 enables all [Connections](/identityproviders) associated with your tenant by default. For the purposes of this tutorial, we will disable all Connections (this helps keep our Application secure, since no one can add themselves using one of our existing Connections), create a new Database Connection, and enable only the newly-created Database Connection. However, you can choose to use any type of Connection.
+
+#### Disable All Existing Connections
+
+Switch over to the Application's **Connections** tab and disable all the Connections using the associated switches.
+
+#### Create a New Connection
+
+In the navigation pane of the Management Dashboard, click on **Connections** > [Database Connections](${manage_url}/#/connections/database).
+
+On the Database Connections page, click on **+Create DB Connection**. Provide a name for your Connection, such as `Helpdesk`.
+
+Click **Save** to proceed.
+
+
+
+Navigate to the **Settings** tab of your new Connection and enable the **Disable Sign Ups** option. For security reasons, this ensures that even users who have the link to our Connection cannot sign themselves up.
+
+
+
+Under the **Applications Using This Connection** section, enable this Connection for your `Users Dashboard` Application.
+
+### Add a User to the New Connection
+
+You will need to add at least one user to your Connection. You can do this via the [Users page](${manage_url}/#/users), where you can specify the Connection for the user during the configuration process.
+
+### Assign Roles to Users
+
+Auth0 grants the user(s) in your Connection access to the Delegated Administration extension based on their roles:
+
+- **Delegated Admin - User**: Grants permission to search for users, create users, open users and execute actions on these users (such as `delete`, `block`, and so on);
+
+- **Delegated Admin - Administrator**: In addition to all of the rights a user has, administrators can see all logs in the tenant and configure Hooks.
+
+To use the extension, users must have either of these roles defined in one of the following fields of their user profiles:
+
+* `user.app_metadata.roles`
+* `user.app_metadata.authorization.roles`
+
+You can set these fields manually or via [rules](/rules).
+
+#### Set User Roles via Rules
+
+This rule gives users from the `IT Department` the `Delegated Admin - Administrator` role and users from `Department Managers` are the `Delegated Admin - User` role.
+
+```js
+function (user, context, callback) {
+ if (context.clientID === 'CLIENT_ID') {
+ // If you are using Node 8, uncomment the following line
+ //const namespace = 'https://${account.tenant}.us8.webtask.io/auth0-delegated-admin';
+ //If you are using Node 12, uncomment the following line
+ //const namespace = 'https://${account.tenant}.us12.webtask.io/auth0-delegated-admin';
+ if (user.groups && user.groups.indexOf('IT Department') > -1) {
+ context.idToken[namespace] = { roles: [ 'Delegated Admin - Administrator' ] };
+ return callback(null, user, context);
+ } else if (user.app_metadata && user.app_metadata.isDepartmentManager && user.app_metadata.department && user.app_metadata.department.length) {
+ context.idToken[namespace] = { roles: [ 'Delegated Admin - User' ] };
+ return callback(null, user, context);
+ }
+
+ return callback(new UnauthorizedError('You are not allowed to use this application.'));
+ }
+
+ callback(null, user, context);
+}
+```
+
+## Install the Extension
+
+Now that we've created and configured an Application, a Connection, and our users, we can install and configure the extension itself.
+
+On the Management Dashboard, navigate to the [Extensions](${manage_url}/#/extensions) page. Click on the **Delegated Administration** box in the list of provided extensions. The **Install Extension** window will open.
+
+
+
+Set the following configuration variables:
+
+- **EXTENSION_CLIENT_ID**: The **Client ID** value of the Application you will use. You can find this value on the **Settings** page of your Application.
+
+- **TITLE** (optional): Set a title for your Application. It will be displayed at the header of the page.
+
+- **CUSTOM_CSS** (optional): Provide a CSS script to customize the look and feel of your Application.
+
+Once done, click **Install**. Your extension is now ready to use!
+
+If you navigate back to the [Applications](${manage_url}/#/applications) view, you will see that the extension automatically created an additional application called `auth0-delegated-admin`.
+
+
+
+Because the application is authorized to access the [Management API](/api/management/v2), you shouldn't modify it.
+
+## Use the Extension
+
+To access your newly created users dashboard, navigate to [**Extensions**](${manage_url}/#/extensions) > **Installed Extensions** > **Delegated Administration Dashboard**.
+
+A new tab will open to display the login prompt.
+
+
+
+Because we disabled signups for this Connection during the configuration period, the login screen doesn't display a Sign Up option.
+
+Once you provide valid credentials, you'll be redirected to the *Delegated Administration Dashboard*.
+
+
+
+## Keep Reading
+
+* [Customize the Delegated Administration Extension Using Hooks](/extensions/delegated-admin/hooks)
+* [Manage Users in the Delegated Administration Extension Dashboard](/extensions/delegated-admin/manage-users)
diff --git a/articles/extensions/delegated-admin/v2/manage-users.md b/articles/extensions/delegated-admin/v2/manage-users.md
new file mode 100644
index 0000000000..83625916d1
--- /dev/null
+++ b/articles/extensions/delegated-admin/v2/manage-users.md
@@ -0,0 +1,92 @@
+---
+description: How to manage users in the Delegated Administration extension
+toc: true
+topics:
+ - extensions
+ - delegated-admin
+ - users
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
+---
+
+# Delegated Administration: Manage Users
+
+In the Application exposed by the Delegated Administration extension, there are two views available: *Users* and *Logs*. On the *Users* view, you can see the display and modify users associated with your Auth0 account.
+
+By default, all users are displayed, but you can filter the displayed list by configuring a [filter hook](/extensions/delegated-admin/hooks#the-filter-hook).
+
+## Available User Actions in the Delegated Administration Dashboard
+
+The table below lists the options you can perform on users, as well as information on whether the option is available via the [Management Dashboard](${manage_url}/#/) and/or the Delegated Administration extension. To limit the number of options someone with access to the Dashboard exposed by the Delegated Administration extension, configure an [access hook](#access-hook).
+
+
+
+
+
Action
+
Available in the Management Dashboard
+
Available in the Delegated Administration Extension
+
+
+
Create User
+
Yes
+
Yes
+
+
+
Contact User
+
Yes
+
No
+
+
+
Block User
+
Yes
+
Yes
+
+
+
Delete User
+
Yes
+
Yes
+
+
+
Send Verification Email
+
Yes
+
Yes
+
+
+
Change Email
+
Yes
+
Yes
+
+
+
Change Password
+
Yes
+
Yes
+
+
+
Reset Password
+
No
+
Yes
+
+
+
+
+Notice the new *Reset Password* option available via the extension. This option will send an email to the user allowing them to choose a new password. To do this click on a user and select *Actions > Reset Password*.
+
+
+
+This will send an email to the user, containing a link to change the password.
+
+If your profile indicates that you have the `Delegated Admin - Administrator` role, the *Logs* view allows you to see a list of authentications made by your users (this tab is only visible to users with the `Delegated Admin - Administrator` role). The contents of this view are a subset of the data displayed in the [Logs Dashboard](${manage_url}/#/logs). The Log Dashboard also displays data on administrative actions taken in the Dashboard.
+
+## Create Users
+
+You can create a new user by selecting the **+ Create User** button on the *Users* view. You need to specify are email and password. Depending on your role, you may not be able to set the *Department* to which the new user belongs.
+
+For example, users with the `Delegated Admin - Administrator` role can see the **Department** field and select any of its values.
+
+
+
+On the other hand, Kelly who has the `Delegated Admin - User` role and belongs to the Finance department cannot see this field. The user she creates will be automatically assigned to the Finance department.
+
+
diff --git a/articles/extensions/delegated-admin/v3/_session-timeout.md b/articles/extensions/delegated-admin/v3/_session-timeout.md
new file mode 100644
index 0000000000..3ddda0e079
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/_session-timeout.md
@@ -0,0 +1,3 @@
+::: panel Session Timeout
+By default, token expiration time is 10 hours. However, when using Delegated Administration, Auth0 doesn't save a token to cookies or `sessionStorage` for security reasons, so you will need to start a new session on each page reload.
+:::
diff --git a/articles/extensions/delegated-admin/v3/hooks/_stepnav.html b/articles/extensions/delegated-admin/v3/hooks/_stepnav.html
new file mode 100644
index 0000000000..38681ec1e0
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/hooks/_stepnav.html
@@ -0,0 +1,14 @@
+
\ No newline at end of file
diff --git a/articles/extensions/delegated-admin/v3/hooks/access.md b/articles/extensions/delegated-admin/v3/hooks/access.md
new file mode 100644
index 0000000000..e6010a7e5f
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/hooks/access.md
@@ -0,0 +1,79 @@
+---
+description: How to use the Access Hook with the Delegated Administration extension
+topics:
+ - extensions
+ - delegated-admin
+ - users
+ - hooks
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
+---
+# Delegated Administration Hooks: The Access Hook
+
+Because the [Filter Hook](/extensions/delegated-admin/v3/hooks/filter) only applies filtering logic, you'll need a second layer of logic to determine if the current user (or the person acting as the administrator) is allowed to access a specific user.
+
+The **Access Hook** allows you to determine if the current user is allowed to read, delete, block, unblock, or update a specific user.
+
+## The Hook Contract
+
+ - **ctx**: The context object
+ - **payload**: The payload object
+ - **action**: The current action (eg: **delete:user**) that is being executed
+ - **user**: The user on which the action is being executed
+ - **callback(error)**: The callback to which you can return an error if access is denied
+
+## Sample Usage
+
+Kelly manages the Finance department, and she should only be able to access users within her department.
+
+```js
+function(ctx, callback) {
+ if (ctx.payload.action === 'delete:user') {
+ return callback(new Error('You are not allowed to delete users.'));
+ }
+
+ // Get the department from the current user's metadata.
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+ if (!department || !department.length) {
+ return callback(new Error('The current user is not part of any department.'));
+ }
+
+ // The IT department can access all users.
+ if (department === 'IT') {
+ return callback();
+ }
+
+ ctx.log('Verifying access:', ctx.payload.user.app_metadata.department, department);
+
+ if (!ctx.payload.user.app_metadata.department || ctx.payload.user.app_metadata.department !== department) {
+ return callback(new Error('You can only access users within your own department.'));
+ }
+
+ return callback();
+}
+```
+
+## Notes
+
+If this hook is not configured, all users will be accessible to the current user.
+
+The Hook supports the following action names (which you set using as the value for **ctx.payload.action**:
+
+- **read:user**
+- **delete:user**
+- **reset:password**
+- **change:password**
+- **change:username**
+- **change:email**
+- **read:devices**
+- **read:logs**
+- **remove:multifactor-provider**
+- **block:user**
+- **unblock:user**
+- **send:verification-email**
+
+<%= include('./_stepnav', {
+ prev: ["Delegated Admin: Hooks", "/extensions/delegated-admin/hooks"]
+}) %>
\ No newline at end of file
diff --git a/articles/extensions/delegated-admin/v3/hooks/filter.md b/articles/extensions/delegated-admin/v3/hooks/filter.md
new file mode 100644
index 0000000000..c0deeadf43
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/hooks/filter.md
@@ -0,0 +1,61 @@
+---
+description: How to use the Filter Hook with the Delegated Administration extension
+topics:
+ - extensions
+ - delegated-admin
+ - users
+ - hooks
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
+---
+# Delegated Administration Hooks: The Filter Hook
+
+By default, users with the **Delegated Admin - User** role see *all* users associated with the Auth0 account. However, you can filter the data users see using the **Filter Hook**.
+
+## The Hook Contract
+
+ - **ctx**: The context object
+ - **callback(error, query)**: The callback to which you can return an error or the [lucene query](/api/management/v2/query-string-syntax) used when filtering the users. The extension will send this query to the [**GET Users** endpoint](/api/management/v2#!/Users/get_users) of the Management API
+
+### Sample Usage
+
+If Kelly manages the Finance department, she should only see the users that are also part of the Finance department. We'll filter the users with respect to the department of the current user (which, in this case, is the Finance department and Kelly, respectively).
+
+```js
+function(ctx, callback) {
+ // Get the department from the current user's metadata.
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+ if (!department || !department.length) {
+ return callback(new Error('The current user is not part of any department.'));
+ }
+
+ // The IT department can see all users.
+ if (department === 'IT') {
+ return callback();
+ }
+
+ // Return the lucene query.
+ return callback(null, 'app_metadata.department:"' + department + '"');
+}
+```
+
+### Search Engine Override
+
+You can override the default search engine by specifying your choice in the response.
+
+```js
+ // Return the lucene query.
+ return callback(null, { query: 'app_metadata.department:"' + department + '"', searchEngine: 'v2' });
+```
+
+## Notes
+
+Do not use single quotes, double quotes, or any other special characters (such as **+** or **-**) in terms on which you'll want to filter. This may cause issues with the Lucene query.
+
+If you do not configure this Hook, the search returns **all users**.
+
+<%= include('./_stepnav', {
+ prev: ["Delegated Admin: Hooks", "/extensions/delegated-admin/hooks"]
+}) %>
diff --git a/articles/extensions/delegated-admin/v3/hooks/index.md b/articles/extensions/delegated-admin/v3/hooks/index.md
new file mode 100644
index 0000000000..737643c706
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/hooks/index.md
@@ -0,0 +1,182 @@
+---
+description: How to customize the behavior of the Delegated Administration extension using Hooks
+toc: true
+topics:
+ - extensions
+ - delegated-admin
+ - users
+ - hooks
+contentType:
+ - how-to
+ - concept
+ - index
+useCase: extensibility-extensions
+---
+
+# Delegated Administration: Hooks
+
+If you're a user assigned the **Delegated Admin - Administrator** role, you can manage the different Hooks and queries that allow you to customize the behavior of the Delegated Administration extension.
+
+To access the configuration area:
+
+1. Log in to the Delegated Administration Dashboard
+2. Click on your name in the top right corner. You'll see a drop-down menu; click on the **Configure** option.
+
+The **Configuration** page to which you're redirected is where you can manage your Hooks and queries.
+
+## Hooks Signature
+
+Hooks always have the following signature:
+
+```js
+function(ctx, callback) {
+ // First do some work
+ ...
+
+ // Done
+ return callback(null, something);
+}
+```
+
+The context (**ctx**) object will expose a few helpers and information about the current request. The following methods and properties are available in every Hook:
+
+* Logging
+* Caching
+* Custom Data
+* Payload and Request
+* Remote Calls
+
+### Logging
+
+To add a message to the Webtask logs (which you can view using the [Realtime Webtask Logs](/extensions/realtime-webtask-logs) extension), call the **log** method:
+
+```js
+ctx.log('Hello there', someValue, otherValue);
+ ```
+
+### Caching
+
+To cache something (such as a long list of departments), you can store it on the context's **global** object. This object will be available until the Webtask container recycles.
+
+```js
+ctx.global.departments = [ 'IT', 'HR', 'Finance' ];
+```
+
+### Custom Data
+
+You can store custom data within the extension. This field is limited to 400kb of data.
+
+```js
+var data = {
+departments: [ 'IT', 'HR', 'Finance' ]
+};
+
+ctx.write(data)
+.then(function() {
+ ...
+})
+.catch(function(err) {
+ ...
+});
+```
+
+To read the data:
+
+```js
+ctx.read()
+.then(function(data) {
+ ...
+})
+.catch(function(err) {
+ ...
+});
+```
+
+### Payload and Request
+
+Each Hook exposes the current payload or request with specific information. The request will always contain information about the user that is logged into the Users Dashboard:
+
+```js
+var currentUser = ctx.request.user;
+```
+
+### Remote Calls
+
+If you want to call an external service (such as an API) to validate data or to load memberships, you can do this using the `request` module.
+
+```js
+function(ctx, callback) {
+var request = require('request');
+ request('http://api.mycompany.com/departments', function (error, response, body) {
+ if (error) {
+ return callback(error);
+ }
+
+ ...
+ });
+}
+```
+
+### The Hook contract:
+
+ - `ctx`: The context object
+ - `payload`: The payload object
+ - `action`: The current action (for example, `delete:user`) that is being executed
+ - `user`: The user on which the action is being executed
+ - `callback(error)`: The callback to which you can return an error if access is denied
+
+Example: Kelly manages the Finance department, and she should only be able to access users within her department.
+
+```js
+function(ctx, callback) {
+ if (ctx.payload.action === 'delete:user') {
+ return callback(new Error('You are not allowed to delete users.'));
+ }
+
+ // Get the department from the current user's metadata.
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+ if (!department || !department.length) {
+ return callback(new Error('The current user is not part of any department.'));
+ }
+
+ // The IT department can access all users.
+ if (department === 'IT') {
+ return callback();
+ }
+
+ ctx.log('Verifying access:', ctx.payload.user.app_metadata.department, department);
+
+ if (!ctx.payload.user.app_metadata.department || ctx.payload.user.app_metadata.department !== department) {
+ return callback(new Error('You can only access users within your own department.'));
+ }
+
+ return callback();
+}
+```
+
+If this hook is not configured, all users will be accessible.
+
+Supported action names:
+
+ - `read:user`
+ - `delete:user`
+ - `reset:password`
+ - `change:password`
+ - `change:username`
+ - `change:email`
+ - `read:devices`
+ - `read:logs`
+ - `remove:multifactor-provider`
+ - `block:user`
+ - `unblock:user`
+ - `send:verification-email`
+
+## Available Hooks
+
+The following Hooks are available for use with your Delegated Administration extension:
+
+* [The Access Hook](/extensions/delegated-admin/v3/hooks/access)
+* [The Filter Hook](/extensions/delegated-admin/v3/hooks/filter)
+* [The Memberships Query Hook](/extensions/delegated-admin/v3/hooks/membership)
+* [The Settings Query Hook](/extensions/delegated-admin/v3/hooks/settings)
+* [The Write Hook](/extensions/delegated-admin/v3/hooks/write)
\ No newline at end of file
diff --git a/articles/extensions/delegated-admin/v3/hooks/membership.md b/articles/extensions/delegated-admin/v3/hooks/membership.md
new file mode 100644
index 0000000000..5d0799bce1
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/hooks/membership.md
@@ -0,0 +1,65 @@
+---
+description: How to use the Memberships Query Hook with the Delegated Administration extension
+topics:
+ - extensions
+ - delegated-admin
+ - users
+ - hooks
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
+---
+# Delegated Administration Hooks: The Memberships Query Hook
+
+When creating a new user, the User Interface shows a drop-down where you can choose the membership(s) you want assigned to a user. These memberships are then defined using the **Memberships Query Hook**.
+
+## The Hook Contract
+
+ - **ctx**: The context object
+ - **callback(error, { createMemberships: true/false, memberships: [ ...] })**: The callback to which you can return an error and an object containing the membership configuration
+
+## Sample Usage
+
+Users of the IT department should be able to create users in other departments. Users from other departments should only be able to create users for their departments.
+
+```js
+function(ctx, callback) {
+ var currentDepartment = ctx.payload.user.app_metadata && ctx.payload.user.app_metadata.department;
+ if (!currentDepartment || !currentDepartment.length) {
+ return callback(null, [ ]);
+ }
+
+ if (currentDepartment === 'IT') {
+ return callback(null, [ 'IT', 'HR', 'Finance', 'Marketing' ]);
+ }
+
+ return callback(null, [ ctx.payload.user.app_metadata.department ]);
+}
+```
+
+## Notes
+
+Because you can only use this query in the UI, you'll need to assign memberships using the **Write Hook** if you need to enforce rules regarding the assignment of users to specific departments.
+
+If there is only one membership group possible, the Memberships field will not show in the UI.
+
+You can allow the end user to enter any value into the **memberships** field by setting **createMemberships** to true:
+
+```js
+function(ctx, callback) {
+ var currentDepartment = ctx.payload.user.app_metadata.department;
+ if (!currentDepartment || !currentDepartment.length) {
+ return callback(null, [ ]);
+ }
+
+ return callback(null, {
+ createMemberships: ctx.payload.user.app_metadata.department === 'IT' ? true : false,
+ memberships: [ ctx.payload.user.app_metadata.department ]
+ });
+}
+```
+
+<%= include('./_stepnav', {
+ prev: ["Delegated Admin: Hooks", "/extensions/delegated-admin/hooks"]
+}) %>
diff --git a/articles/extensions/delegated-admin/v3/hooks/settings.md b/articles/extensions/delegated-admin/v3/hooks/settings.md
new file mode 100644
index 0000000000..2a032aaaba
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/hooks/settings.md
@@ -0,0 +1,354 @@
+---
+description: How to use the Settings Query Hook with the Delegated Administration extension
+toc: true
+topics:
+ - extensions
+ - delegated-admin
+ - users
+ - hooks
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
+---
+# Delegated Administration Hooks: The Settings Query Hook
+
+The **Settings Query Hook** allows you to customize the look and feel of the Delegated Admin extension.
+
+## The Hook Contract
+
+ - **ctx**: The context object
+ - **request.user**: The user currently logged in
+ - **locale**: The locale (as inferred from the URL) -- `https://${account.tenant}.us.webtask.io/auth0-delegated-admin/en/users` will set **locale** to `en`.
+ - **callback(error, settings)**: The callback to which you can return an error and a settings object
+
+## Sample Usage
+
+```js
+function(ctx, callback) {
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+
+ return callback(null, {
+ // Only these connections should be visible in the connections picker. If only one connection is available, the connections picker will not be shown in the UI.
+ connections: [ 'Username-Password-Authentication', 'My-Custom-DB' ],
+ // The dictionary allows you to overwrite the title of the dashboard and the "Memberships" label in the Create User dialog.
+ dict: {
+ title: department ? department + ' User Management' : 'User Management Dashboard',
+ memberships: 'Departments',
+ menuName: ctx.request.user.name
+ },
+ // The CSS option allows you to inject a custom CSS file depending on the context of the current user (eg: a different CSS for every customer)
+ css: (department && department !== 'IT') && 'https://rawgit.com/auth0-extensions/auth0-delegated-administration-extension/master/docs/theme/fabrikam.css',
+ // This option allows you to restrict creating new users
+ canCreateUser: (department === 'IT')
+ });
+}
+```
+
+### Properties
+
+- **connections**: The list of the connections this admin is allowed to create and edit users within
+- **dict**: The dictionary allows you to overwrite the title of the dashboard and the **Memberships** label in the Create User dialog
+ - **dict.title**: The title to display at the top of the UI
+ - **dict.memberships**: The label to set for memberships fields
+ - **dict.menuName**: The name to set for the upper right-hand dropdown menu
+ - **dict.logoutUrl**: An alternate URL for the logout menu option
+- **userFields**: An array of user fields (see [Custom Fields](#custom-fields))
+- **css**: A string URL to import CSS
+- **altcss**: A string URL to import a second set of CSS. You can use this to specify things like accessibility CSS for larger fonts. The user will be presented with a menu item allowing them to toggle this set of CSS on/off
+- **languageDictionary**: A string URL or Dictionary Object (see [Localization](#localization))
+- **suppressRawData**: Set to **true** to skip pages that show raw JSON
+- **errorTranslator**: A function that translates error messages based on localization. Example: `(function (error, languageDictionary) { return languageDictionary.customErrors[error] || error; }).toString()`
+- **canCreateUser**: A boolean flag. If set to `false`, removes `Create User` button and forbids creating new users, `true` by default.
+
+## Custom Fields
+
+Beginning with version 3.0 of the Delegated Admin Extension, you can define custom fields and specify their values. Custom fields can be stored in the **user metadata** and **app metadata** fields accessible during the user creation or update processes.
+
+You may also customize existing fields defined by Auth0, such as email, username, name, and connection.
+
+To utilize custom fields, you must:
+
+- Add your list of **userFields** to the Settings Query Hook
+- Implement a [Write Hook](/extensions/delegated-admin/v3/hooks/write). Custom Fields require the use of the [Write Hook](/extensions/delegated-admin/v3/hooks/write) to properly update `user_metadata` and `app_metadata`. You must [update the user object passed to the callback function](/extensions/delegated-admin/v3/hooks/write#sample-usage) with the `user_metadata` and `app_metadata` from the context (`ctx` object) provided to the hook.
+
+Sample schema for **userFields**:
+
+```js
+userFields: [
+ {
+ "property": string, // required
+ "label": string,
+ "sortProperty": string,
+ "display": true || function.toString(),
+ "search": false || {
+ "display": true || function.toString()
+ "listOrder": 1,
+ "listSize": string(###%), // e.g. 15%
+ "filter": boolean,
+ "sort": boolean
+ },
+ "edit": false || {
+ "display": true || function.toString()
+ "type": "text || select || password || hidden",
+ "component": "InputText || Input Combo || InputMultiCombo || InputSelectCombo",
+ "options": Array(string) || Array ({ "value": string, "label": string }),
+ "disabled": true || false,
+ "validationFunction": function.toString()
+ },
+ "create": false || {
+ "display": true || function.toString()
+ "type": "text || select || password || hidden",
+ "component": "InputText || Input Combo || InputMultiCombo || InputSelectCombo",
+ "options": Array(string) || Array ({ "value": string, "label": string }),
+ "disabled": true || false,
+ "validationFunction": function.toString()
+ }
+ },
+ ...
+]
+```
+
+- **property** (**required**): The property name of the **ctx.payload** object for the Write hook. In the Write hook, `"property": "app_metadata.dbId"` sets `ctx.payload.app_metadata.dbId`
+- **label**: The label that will be used when adding a label to the field on the user info page, create page, edit profile page, or search page
+- **sortProperty**: If sorting by a different field than this for the search table, use this field. Dot notation is allowed.
+- **display**: true || false || stringified => This is the default display value. If not overridden in search, edit, or create, it will use this value.
+ - if `true` will just return `user.`
+ - Default: if `false` this value will not be displayed on any page (unless overridden in search, edit, or create)
+ - if stringified function: executes function to get the value to display. Example: `(function display(user, value, languageDictionary) { return moment(value).fromNow(); }).toString()`
+- **search**: false || object => This describes how this field will behave on the search page
+ - Default: if `false` will not show up in the search table
+ - **search.display**: This will override the default display value
+ - **search.listOrder**: This will specify the column order for the search display table
+ - **search.listSize**: This will specify the default width of the column
+ - **search.filter**: This will specify whether to allow this field to be search in the search dropdown. Default is false.
+ - **search.sort**: This will specify whether this column is sortable. Use sortProperty if you want to sort by a field other than property. Default is false.
+- **edit**: false || object => This describes whether the field shows up on the edit dialogs. If not a default field and set to an object, this will show up in the `Change Profile` page on the User Actions dropdown on the user page.
+ - Default: if `false` will not show up on any edit/update page
+ - **edit.display**: This will override the default display value
+ - **edit.required**: set to true to fail if it does not have a value. Default is false.
+ - **edit.type** **required**: text || select || password
+ - **edit.component**: InputText || Input Combo || InputMultiCombo || InputSelectCombo
+ - **InputText** (default): A simple text box
+ - **InputCombo**: A searchable dropdown, single value only
+ - **InputMultiCombo**: A searchable dropdown, with multiple values allowed
+ - **InputSelectCombo**: A select dropdown of options
+ - **edit.options**: if component is one of InputCombo, InputMultiCombo, InputSelectCombo, the option values need to be specified.
+ - **Array(string)**: An array of values (the label and value fields will be set to the same value)
+ - **Array({ "value": string, "label": string })**: Allows you to set separate values for the value and label. NOTE: This will result in the value in the write hook having the same value, but it can be trimmed down to just the value in the write hook.
+ - Server-side validation will ensure that any value specified for this field appears in the options array
+ - **edit.disabled**: `true` if the component should be read only; default is false
+ - **edit.validateFunction**: stringified function for validation. Note that this validation function will run on both the server- and client-side. Example: `(function validate(value, values, context, languageDictionary) { if (value...) return 'something went wrong'; return false; }).toString()`
+- **create**: false || object => This describes whether the field shows up on the create dialog.
+ - Default: if `false` will not show up on the create page
+ - **create.placeholder**: Provide placeholder text to show when input is empty.
+ - **create.required**: set to true to fail if it does not have a value. Default is false.
+ - **create.type** **required**: text || select || password
+ - **create.component**: InputText || Input Combo || InputMultiCombo || InputSelectCombo
+ - **InputText** (default): A text box. Default for type text and password.
+ - **InputCombo**: A searchable dropdown, single value only
+ - **InputMultiCombo**: A searchable dropdown, with multiple values allowed
+ - **InputSelectCombo**: A select dropdown of options
+ - **create.options**: if component is one of InputCombo, InputMultiCombo, InputSelectCombo, the option values need to be specified.
+ - **Array(string)**: A simple array of values, label and value will be set to the same
+ - **Array({ "value": string, "label": string })**: Allows you to set separate values for both the value and label. NOTE: This will result in the value in the write hook having the same value, but it can be trimmed down to just the value in the write hook.
+ - The server side validation will ensure that any value specified for this field is in the options array.
+ - **create.disabled**: true if component should be read only, default is false
+ - **create.validateFunction**: stringified function for checking the validation
+ - Example: `(function validate(value, values, context, languageDictionary) { if (value...) return 'something went wrong'; return false; }).toString()`
+ - This validation function will run on both the server- and client-side.
+
+## Pre-Defined Fields
+
+There are a set of pre-defined, searchable fields for default behavior.
+
+You can override the default behavior by adding the field as a userField and then overriding the behavior you would like to change. This would often be done to suppress a field by setting the display to false.
+
+### Search Fields
+
+- **name**: A constructed field from other fields: default display function: `(function(user, value) { return (value || user.nickname || user.email || user.user_id); }).toString()`
+- **email**: email address or N/A
+- **last_login_relative**: The last login time
+- **logins_count**: The number of logins
+- **connection**: Their database connection
+
+### User Info Fields:
+
+- **user_id**: The user ID
+- **name**: The user's name
+- **username**: The user's username
+- **email**: The user's email
+- **identity.connection**: The connection value
+- **isBlocked**: Whether or not the user is blocked
+- **blocked_for**: Whether or not the user has anomaly detection blocks
+- **last_ip**: What the last IP was the user used to log in
+- **logins_count**: How many times the user has logged in
+- **currentMemberships**: The list of memberships for this user
+- **created_at**: How long ago the user was created.
+- **updated_at**: How long ago the user was updated.
+- **last_login**: How long ago the user last logged in.
+
+### Create and Edit User Fields
+
+- **connection**: The user's database
+- **password**: The new password
+- **repeatPassword**: A repeat of the user's password
+- **email**: The user's email
+- **username**: The user's username
+
+### Sample Usage
+
+```js
+function(ctx, callback) {
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+
+ return callback(null, {
+ // Only these connections should be visible in the connections picker.
+ // If only one connection is available, the connections picker will not be shown in the UI.
+ connections: [ 'Username-Password-Authentication', 'My-Custom-DB' ],
+ // The dictionary allows you to overwrite the title of the dashboard and the "Memberships" label in the Create User dialog.
+ dict: {
+ title: department ? department + ' User Management' : 'User Management Dashboard',
+ memberships: 'Departments'
+ },
+ // User Fields are the custom fields that can be displayed in create and edit, and can also be used for searching, and can be used to customize the view user page
+ userFields: [
+ {
+ "label": "Connection",
+ "property": "connection",
+ "display": false,
+ "create": false,
+ "edit": false,
+ "search": false
+ },
+ {
+ "label": "First Name",
+ "property": "user_metadata.given_name",
+ "display": true,
+ "create": {
+ "type": "text"
+ },
+ "edit": {
+ "type": "text"
+ },
+ "search": {
+ "listSize": "10%",
+ "listOrder": 0
+ }
+ },
+ {
+ "label": "Last Name",
+ "property": "user_metadata.family_name",
+ "display": true,
+ "create": {
+ "type": "text"
+ },
+ "edit": {
+ "type": "text"
+ },
+ "search": {
+ "listSize": "10%",
+ "listOrder": 1,
+ "sort": true
+ }
+ }
+ ],
+ // The CSS option allows you to inject a custom CSS file depending on the context of the current user (eg: a different CSS for every customer)
+ css: (department && department !== 'IT') && 'https://rawgit.com/auth0-extensions/auth0-delegated-administration-extension/master/docs/theme/fabrikam.css'
+ });
+}
+```
+
+## Localization
+
+Beginning with version 3.0 of the Delegated Admin Extension, you can provide a language dictionary for use with localization. The language dictionary is used only for static page content - for field level content, you must use **userFields** labels.
+
+::: note
+Localization is aimed at those working with non-administrative functions when managing users. Auth0 currently does not support localization on any of the Configuration pages.
+:::
+
+To specify the locale, you can use the path. For example: https://${account.tenant}.us.webtask.io/auth0-delegated-admin/en/users will set context.locale to `en` in the settings query.
+
+The **languageDictionary** is set as part of the settings query, which allows you to:
+
+* Explicitly define **languageDictionary**
+* Provide URL to fetch the contents for the **languageDictionary** parameter
+
+Here is a sample of what a [complete Language Dictionary file](https://rawgit.com/auth0-extensions/auth0-delegated-administration-extension/master/tests/utils/en.json) looks like.
+
+### Example: Providing a Link to a Language Dictionary File
+
+```js
+function(ctx, callback) {
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+
+ return callback(null, {
+ // Only these connections should be visible in the connections picker.
+ // If only one connection is available, the connections picker will not be shown in the UI.
+ connections: [ 'Username-Password-Authentication', 'My-Custom-DB' ],
+ // The dictionary allows you to overwrite the title of the dashboard and the "Memberships" label in the Create User dialog.
+ dict: {
+ title: department ? department + ' User Management' : 'User Management Dashboard',
+ memberships: 'Departments'
+ },
+ // User Fields are the custom fields that can be displayed in create and edit, and can also be used for searching, and can be used to customize the view user page
+ userFields: [
+ {
+ "label": "Conexión",
+ "property": "connection",
+ },
+ {
+ "label": "Correo Electrónico",
+ "property": "email",
+ },
+ ...
+ ],
+ // The CSS option allows you to inject a custom CSS file depending on the context of the current user (eg: a different CSS for every customer)
+ css: (department && department !== 'IT') && 'https://rawgit.com/auth0-extensions/auth0-delegated-administration-extension/master/docs/theme/fabrikam.css',
+ languageDictionary: 'https://your-cdn.com/locale/es.json'
+ });
+}
+```
+
+### Example: Providing a Language Dictionary Object
+
+```js
+function(ctx, callback) {
+ var department = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+
+ return callback(null, {
+ // Only these connections should be visible in the connections picker.
+ // If only one connection is available, the connections picker will not be shown in the UI.
+ connections: [ 'Username-Password-Authentication', 'My-Custom-DB' ],
+ // The dictionary allows you to overwrite the title of the dashboard and the "Memberships" label in the Create User dialog.
+ dict: {
+ title: department ? department + ' User Management' : 'User Management Dashboard',
+ memberships: 'Departments'
+ },
+ // User Fields are the custom fields that can be displayed in create and edit, and can also be used for searching, and can be used to customize the view user page
+ userFields: [
+ {
+ "label": "Conexión",
+ "property": "connection",
+ },
+ {
+ "label": "Correo Electrónico",
+ "property": "email",
+ },
+ ...
+ ],
+ // The CSS option allows you to inject a custom CSS file depending on the context of the current user (eg: a different CSS for every customer)
+ css: (department && department !== 'IT') && 'https://rawgit.com/auth0-extensions/auth0-delegated-administration-extension/master/docs/theme/fabrikam.css',
+ languageDictionary: {
+ loginsCountLabel: 'Cantidad de Logins:',
+ searchBarPlaceholder: 'Busqueda de usuarios usando la sintaxis de Lucene',
+ deviceNameColumnHeader: 'Dispositivo',
+ ...
+ }
+ });
+}
+```
+
+<%= include('./_stepnav', {
+ prev: ["Delegated Admin: Hooks", "/extensions/delegated-admin/hooks"]
+}) %>
diff --git a/articles/extensions/delegated-admin/v3/hooks/write.md b/articles/extensions/delegated-admin/v3/hooks/write.md
new file mode 100644
index 0000000000..d545e8f82b
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/hooks/write.md
@@ -0,0 +1,89 @@
+---
+description: How to use the Write Hook with the Delegated Administration extension
+topics:
+ - extensions
+ - delegated-admin
+ - users
+ - hooks
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
+---
+# Delegated Administration Hooks: The Write Hook
+
+The Write Hook, which runs anytime you create or update a user, allows you to do things like:
+
+* Changing the user's password
+* Changing the user's email address
+* Updating the user's profile
+
+You can also use the Write Hook to set default values for newly-created users automatically. For example, you might want to automatically assign a user to the same group, department, or vendor as the ones to which you've been assigned.
+
+::: warning
+Auth0 only supports user creation with Database Connections.
+:::
+
+## The Hook Contract
+
+ - **ctx**: The context object.
+ - **request.originalUser**: The current user's values where the **payload** is the new set of fields. Only available when the method is **update**
+ - **payload**: The payload object
+ - **memberships**: An array of memberships that were selected in the UI when creating the user
+ - **email**: The email address of the user
+ - **password**: The password of the user
+ - **connection**: The name of the database connection
+ - **app_metadata**: The data that's included if a Custom Field being modified is saved in `app_metadata`.
+ - **user_metadata**: The data that's included if a Custom Field being modified is saved in `user_metadata`.
+ - **userFields**: The user fields array (if specified in the [settings query](#the-settings-query-hook))
+ - **method**: Either **create** or **update** depending on whether this is being called as a result of a create or an update call
+ - **callback(error, user)**: The callback to which you can return an error and the user object that should be sent to the Management API
+
+## Sample Usage
+
+Kelly manages the Finance department. When she creates users, these users should be assigned as members of the Finance department.
+
+```js
+function(ctx, callback) {
+ var newProfile = {
+ email: ctx.payload.email,
+ password: ctx.payload.password,
+ connection: ctx.payload.connection,
+ user_metadata: ctx.payload.user_metadata,
+ app_metadata: {
+ department: ctx.payload.memberships && ctx.payload.memberships[0],
+ ...ctx.payload.app_metadata
+ }
+ };
+
+ if (!ctx.payload.memberships || ctx.payload.memberships.length === 0) {
+ return callback(new Error('The user must be created within a department.'));
+ }
+
+ // Get the department from the current user's metadata.
+ var currentDepartment = ctx.request.user.app_metadata && ctx.request.user.app_metadata.department;
+ if (!currentDepartment || !currentDepartment.length) {
+ return callback(new Error('The current user is not part of any department.'));
+ }
+
+ // If you're not in the IT department, you can only create users within your own department.
+ // IT can create users in all departments.
+ if (currentDepartment !== 'IT' && ctx.payload.memberships[0] !== currentDepartment) {
+ return callback(new Error('You can only create users within your own department.'));
+ }
+
+ if (ctx.method === 'update') {
+ // If updating, only set the fields we need to send
+ Object.keys(newProfile).forEach(function(key) {
+ if (newProfile[key] === ctx.request.originalUser[key]) delete newProfile[key];
+ });
+ }
+
+ // This is the payload that will be sent to API v2. You have full control over how the user is created in API v2.
+ return callback(null, newProfile);
+}
+```
+
+<%= include('./_stepnav', {
+ prev: ["Delegated Admin: Hooks", "/extensions/delegated-admin/hooks"]
+}) %>
diff --git a/articles/extensions/delegated-admin/v3/index.md b/articles/extensions/delegated-admin/v3/index.md
new file mode 100644
index 0000000000..55e03b3f4e
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/index.md
@@ -0,0 +1,117 @@
+---
+title: Delegated Administration Extension
+description: Learn about Auth0's Delegated Administration Extension, which allows you to expose the Users section of the Auth0 Dashboard to a select group of users without allowing them access to the rest of the Dashboard.
+toc: true
+topics:
+ - extensions
+ - delegated-admin
+contentType:
+ - how-to
+ - concept
+ - index
+useCase: extensibility-extensions
+---
+
+# Delegated Administration Extension
+
+The **Delegated Administration Extension (DAE)** allows you to grant a select group of people administrative permissions to the [Users page](${manage_url}/#/users) of the Auth0 Dashboard without providing access to any other area. This guide will show you how to do this by exposing the [Users area](${manage_url}/#/users) as an Auth0 application.
+
+## Steps
+
+To set up the Delegate Administration Extension (DAE), you must:
+
+1. [Register an Application with Auth0](#register-an-application-with-auth0)
+2. [Create a database connection](#create-a-database-connection)
+3. [Disable all other connections for your Auth0 Application](#disable-all-other-connections-for-your-auth0-application)
+4. [Create a user for the database connection](#create-a-user-for-the-database-connection)
+5. [Assign roles to the user](#assign-roles-to-the-user)
+6. [Install and configure the extension](#install-and-configure-the-extension)
+7. [Use the extension](#use-the-extension)
+
+### Register an Application with Auth0
+
+First, you must create the Application that the Delegated Administration Extension will expose to those who should have administrative privileges for the Users page. To do this, [create a delegated admin application](/dashboard/guides/extensions/delegated-admin-create-app) in Auth0.
+
+When finished, make sure to note the application's **Client ID**.
+
+### Create a database connection
+
+In this example, a database connection will serve as the source of your users who are allowed access to the Users area. To configure this, [create a database connection](/dashboard/guides/connections/set-up-connections-database).
+
+While setting up your connection, make sure you use the following settings:
+
+* For connection name, use an appropriate name, such as `HelpDesk`.
+* Enable the **Disable Sign Ups** toggle, which, for security purposes, will ensure that even users who have the link to the database connection cannot sign themselves up.
+
+### Disable all other connections for your Auth0 Application
+
+By default, Auth0 enables all connections associated with your tenant when you create a new Application. For this example, we will disable all connections other than our newly-created database connection. This will help keep the application secure because no one will be able to add themselves using one of our existing connections.
+
+To configure this, [update application connections](/dashboard/guides/applications/update-app-connections).
+
+### Create a user for the database connection
+
+To continue, you must [create at least one user](/dashboard/guides/users/create-users) and attach it to your connection.
+
+### Assign roles to the user
+
+<%= include('../../../_includes/_rbac_vs_extensions') %>
+
+Auth0 grants access to the Delegated Administration Extension (DAE) for the user(s) attached to your connection based on their roles. DAE-specific roles include:
+
+- **Delegated Admin - User**: Grants permission to search for users, create users, open users, and execute actions on users (e.g., `delete`, `block`).
+
+- **Delegated Admin - Administrator**: Grants all the rights of **Delegated Admin - User**, plus the ability to see all logs in the tenant and configure Hooks.
+
+- **Delegated Admin - Auditor**: Grants permission to search for users and view user information, but does not allow any changes to be made. This role also changes the UI to remove action-based buttons.
+
+- **Delegated Admin - Operator**: Grants permission to access user management and logs, but does not allow access to the extension configuration section.
+
+When working with roles, we recommend that you use the Authorization Core feature set:
+
+1. [Create DAE roles](/dashboard/guides/roles/create-roles). The names of the roles you create must match the names of the [pre-defined DAE roles above](#assign-roles-to-users).
+
+2. [Assign the DAE role to a user manually](/dashboard/guides/users/assign-roles-users), then add the user roles to the DAE namespace in the ID Token using the following rule, remembering to replace the `CLIENT_ID` placeholder with your delegated admin application's **Client ID**.
+
+```js
+function (user, context, callback) {
+ if (context.clientID === 'CLIENT_ID') {
+ const namespace = 'https://example.com/auth0-delegated-admin';
+ context.idToken[namespace] = {
+ roles: (context.authorization || {}).roles
+ };
+ }
+ callback(null, user, context);
+}
+```
+
+See this guide with more [information about creating rules](/dashboard/guides/rules/create-rules).
+
+::: note
+Your claim should be [namespaced](/tokens/guides/create-namespaced-custom-claims).
+:::
+
+::: note
+Using Authorization Core will define roles in the `context.authorization` object.
+
+If you choose not to use Authorization Core, you should define DAE roles in one of the following fields on the user profile:
+
+* `user.app_metadata.roles`
+* `user.app_metadata.authorization.roles`
+:::
+
+## Install and configure the extension
+
+Now that we've created and configured an application, a connection, and our user, we can [install and configure the Delegated Admin Extension](/dashboard/guides/extensions/delegated-admin-install-extension) itself.
+
+## Use the extension
+
+Once installed, you are ready to [use the Delegated Admin Extension](/dashboard/guides/extensions/delegated-admin-use-extension).
+
+<%= include('./_session-timeout.md') %>
+
+## Keep reading
+
+* [Customizing the Delegated Administration Extension using Hooks](/extensions/delegated-admin/hooks)
+
+* [Managing users in the Delegated Administration Dashboard](/extensions/delegated-admin/manage-users)
diff --git a/articles/extensions/delegated-admin/v3/manage-users.md b/articles/extensions/delegated-admin/v3/manage-users.md
new file mode 100644
index 0000000000..b943aaf9a0
--- /dev/null
+++ b/articles/extensions/delegated-admin/v3/manage-users.md
@@ -0,0 +1,106 @@
+---
+description: How to manage users in the Delegated Administration extension
+toc: true
+topics:
+ - extensions
+ - delegated-admin
+ - users
+contentType:
+ - how-to
+ - concept
+useCase: extensibility-extensions
+---
+
+# Delegated Administration: Manage Users
+
+In the Application exposed by the Delegated Administration extension, there are two views available: *Users* and *Logs*. On the *Users* view, you can see the display and modify users associated with your Auth0 account.
+
+By default, all users are displayed, but you can filter the displayed list by configuring a [filter hook](/extensions/delegated-admin/v3/hooks/filter).
+
+## Available User Actions in the Delegated Administration Dashboard
+
+The table below lists the options you can perform on users, as well as information on whether the option is available via the [Management Dashboard](${manage_url}/#/) and/or the Delegated Administration extension. To limit the number of options someone with access to the Dashboard exposed by the Delegated Administration extension, configure an [access hook](/extensions/delegated-admin/v3/hooks/access).
+
+
+
+
+
Action
+
Available in the Management Dashboard
+
Available in the Delegated Administration Extension
+
+
+
Create User
+
Yes
+
Yes
+
+
+
Contact User
+
Yes
+
No
+
+
+
Block User
+
Yes
+
Yes
+
+
+
Delete User
+
Yes
+
Yes
+
+
+
Send Verification Email
+
Yes
+
Yes
+
+
+
Change Email
+
Yes
+
Yes
+
+
+
Change Password
+
Yes
+
Yes
+
+
+
Reset Password
+
No
+
Yes
+
+
+
Change Profile
+
Yes
+
Yes
+
+
+
Remove MFA
+
No
+
Yes
+
+
+
+
+The *Change Profile* option is available only if you have configured custom fields.
+
+Notice the new *Reset Password* option available via the extension. This option will send an email to the user allowing them to choose a new password. To do this click on a user and select *Actions > Reset Password*.
+
+
+
+This will send an email to the user, containing a link to change the password.
+
+If your profile indicates that you have the `Delegated Admin - Administrator` role, the *Logs* view allows you to see a list of authentications made by your users (this tab is only visible to users with the `Delegated Admin - Administrator` role). The contents of this view are a subset of the data displayed in the [Logs Dashboard](${manage_url}/#/logs). The Log Dashboard also displays data on administrative actions taken in the Dashboard.
+
+## Create Users
+
+You can create a new user by selecting the **+ Create User** button on the *Users* view. You need to specify are email and password. Depending on your role, you may not be able to set the *Department* to which the new user belongs.
+
+For example, users with the `Delegated Admin - Administrator` role can see the **Department** field and select any of its values.
+
+
+
+On the other hand, Kelly who has the `Delegated Admin - User` role and belongs to the Finance department cannot see this field. The user she creates will be automatically assigned to the Finance department.
+
+
+
+<%= include('./_session-timeout.md') %>
diff --git a/articles/extensions/deploy-cli/_includes/_limitations.md b/articles/extensions/deploy-cli/_includes/_limitations.md
new file mode 100644
index 0000000000..3f26e0cdb8
--- /dev/null
+++ b/articles/extensions/deploy-cli/_includes/_limitations.md
@@ -0,0 +1,3 @@
+### Limitations
+
+Some of the settings cannot be exported, such as `rulesConfigs` values. After exporting, you may need to update the values in `tenant.yaml` if you see schema-related errors during the import process.
diff --git a/articles/extensions/deploy-cli/_includes/_strip-option.md b/articles/extensions/deploy-cli/_includes/_strip-option.md
new file mode 100644
index 0000000000..ab0a70fece
--- /dev/null
+++ b/articles/extensions/deploy-cli/_includes/_strip-option.md
@@ -0,0 +1 @@
+When importing objects into Auth0 tenants, Auth0 generates new IDs. To avoid import failure, identifier fields are stripped from the Auth0 objects on export by default. To override this behavior, use `--export_ids` or `AUTH0_EXPORT_IDENTIFIERS: true`.
diff --git a/articles/extensions/deploy-cli/_includes/_upgrade-v4.md b/articles/extensions/deploy-cli/_includes/_upgrade-v4.md
new file mode 100644
index 0000000000..beab3977fd
--- /dev/null
+++ b/articles/extensions/deploy-cli/_includes/_upgrade-v4.md
@@ -0,0 +1,9 @@
+::: panel Upgrading to Deploy CLI Tool v4
+Upgrading to Deploy CLI Tool v4 requires that the **auth0-deploy-cli-extension** application be granted the following additional permissions (scopes) for the Auth0 Management API: `create:hooks`, `read:hooks`, `update:hooks`, and `delete:hooks`. Upgrading the **Auth0 Deploy CLI** extension will take care of this automatically. To upgrade the extension:
+
+1. Navigate to the [Extensions](${manage_url}/#/extensions) page in the [Auth0 Dashboard](${manage_url}), and click the **Installed Extensions** tab.
+
+2. Locate **Auth0 Deploy CLI**, click **Upgrade**, and confirm. Wait for the upgrade to complete.
+
+If necessary, you can check and [manually modify required scopes](/extensions/deploy-cli/guides/create-deploy-cli-application-manually#modify-deploy-cli-application-scopes).
+:::
\ No newline at end of file
diff --git a/articles/extensions/deploy-cli/guides/call-deploy-cli-programmatically.md b/articles/extensions/deploy-cli/guides/call-deploy-cli-programmatically.md
new file mode 100644
index 0000000000..4347f51a29
--- /dev/null
+++ b/articles/extensions/deploy-cli/guides/call-deploy-cli-programmatically.md
@@ -0,0 +1,67 @@
+---
+title: Call Deploy CLI Tool Programmatically
+description: Learn how call the Auth0 Deploy Command Line Interface (CLI) programmatically.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+# Call Deploy CLI Tool Programmatically
+
+You can call the CLI tool programmatically as shown in the following example:
+
+```js
+import { deploy, dump } from 'auth0-deploy-cli';
+
+const config = {
+ AUTH0_DOMAIN: process.env.AUTH0_DOMAIN,
+ AUTH0_CLIENT_SECRET: process.env.AUTH0_CLIENT_SECRET,
+ AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID,
+ AUTH0_ALLOW_DELETE: false
+};
+
+
+// Export Tenant Config
+dump({
+ output_folder: 'path/to/yaml/or/directory', // Input file for directory, change to .yaml for YAML
+ base_path: basePath, // Allow to override basepath, if not take from input_file
+ config_file: configFile, // Option to a config json
+ config: configObj, // Option to sent in json as object
+ strip, // Strip the identifier field for each object type
+ secret // Optionally pass in auth0 client secret separate from config
+})
+ .then(() => console.log('yey dump was successful'))
+ .catch(err => console.log(`Oh no, something went wrong. <%= "Error: ${err}" %>`));
+
+
+// Import tenant config
+deploy({
+ input_file: 'path/to/yaml/or/directory', // Input file for directory, change to .yaml for YAML
+ base_path: basePath, // Allow to override basepath, if not take from input_file
+ config_file: configFile, // Option to a config json
+ config: configObj, // Option to sent in json as object
+ env, // Allow env variable mappings from process.env
+ secret // Optionally pass in auth0 client secret separate from config
+})
+ .then(() => console.log('yey deploy was successful'))
+ .catch(err => console.log(`Oh no, something went wrong. <%= "Error: ${err}" %>`));
+```
+
+## Troubleshooting
+
+The `auth0-deploy-cli` tool uses the Management API to pass through objects for create, update, and delete actions.
+
+You may occasionally see `Bad Request` and `Payload validation` errors returned by the Management API. These errors usually mean the object you're working with has attributes which are not writable or no longer available. This can happen when you are exporting from an older Auth0 tenant and importing into a newly-created tenant.
+
+If this is the case, update your configuration to support the new object format used by Auth0.
+
+## Keep reading
+
+* [Install the Deploy CLI Tool](/extensions/deploy-cli/guides/install-deploy-cli)
+* [Incorporate Deploy CLI into Build Environment](/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment)
+* [Import/Export Tenant Configuration to a Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [Import/Export Tenant Configuration to a YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
+* [Deploy CLI Tool Options](/extensions/deploy-cli/references/deploy-cli-options)
+* [Troubleshooting Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
\ No newline at end of file
diff --git a/articles/extensions/deploy-cli/guides/create-deploy-cli-application-manually.md b/articles/extensions/deploy-cli/guides/create-deploy-cli-application-manually.md
new file mode 100644
index 0000000000..89ca93dd16
--- /dev/null
+++ b/articles/extensions/deploy-cli/guides/create-deploy-cli-application-manually.md
@@ -0,0 +1,114 @@
+---
+title: Create and Configure the Deploy CLI Application Manually
+description: Learn how to create and configure the Deploy CLI application for use with the Deploy CLI tool. This can be done programmatically using the Auth0 Deploy CLI extension.
+topics:
+ - extensions
+ - deploy-cli
+ - dashboard
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+# Create and Configure the Deploy CLI Application Manually
+
+To use the Deploy CLI tool, your tenant must be configured appropriately.
+
+::: note
+Generally, you do this programmatically by [installing the **Auth0 Deploy CLI** extension](/extensions/deploy-cli/guides/install-deploy-cli#install-the-deploy-cli-extension), which will create and configure an Application that is authorized to call the Management API.
+:::
+
+Sometimes, you may wish to create and configure this application manually. At a later time, you may also want to modify scopes for an application that has been created previously.
+
+## Create the Initial Deploy CLI Application
+
+To create and configure the initial Deploy CLI Application:
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}), and click **+ Create Application**.
+
+2. Enter `auth0-deploy-cli-extension` as the name for your Application, select **Machine to Machine Applications**, and click **Create**.
+
+
+
+3. When asked which API you want to call from your application, select **Auth0 Management API**.
+
+
+
+4. Select the [required scopes](#required-scopes) to enable them for your Application, and click **Authorize**. These scopes will be issued as part of your Application's Access Token.
+
+
+
+## Modify Deploy CLI Application Scopes
+To modify permissions (scopes) for an application that has been created previously:
+
+1. Navigate to the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}/), and click the `auth0-deploy-cli-extension` application.
+
+
+
+2. Click the **APIs** tab, expand the **Auth0 Management API**, and enable any [required scopes](#required-scopes) that appear to have been disabled.
+
+
+
+::: warning
+If the APIs tab is not visible:
+
+1. For **Application Type**, and select **Machine to Machine**.
+
+2. Click **Save Changes**, then refresh the page. The APIs tab should now be visible.
+:::
+
+## Required Scopes
+
+The following scopes are required to be enabled on the `auth0-deploy-cli-extension` Application to ensure it is configured for proper access to the Management API.
+
+ - read:client_grants
+ - create:client_grants
+ - delete:client_grants
+ - update:client_grants
+ - read:clients
+ - update:clients
+ - delete:clients
+ - create:clients
+ - read:client_keys
+ - update:client_keys
+ - delete:client_keys
+ - create:client_keys
+ - read:connections
+ - update:connections
+ - delete:connections
+ - create:connections
+ - read:resource_servers
+ - update:resource_servers
+ - delete:resource_servers
+ - create:resource_servers
+ - read:rules
+ - update:rules
+ - delete:rules
+ - create:rules
+ - read:hooks
+ - create:hooks
+ - update:hooks
+ - delete:hooks
+ - read:rules_configs
+ - update:rules_configs
+ - delete:rules_configs
+ - read:email_provider
+ - update:email_provider
+ - delete:email_provider
+ - create:email_provider
+ - read:tenant_settings
+ - update:tenant_settings
+ - read:grants
+ - delete:grants
+ - read:guardian_factors
+ - update:guardian_factors
+ - read:email_templates
+ - create:email_templates
+ - update:email_templates
+ - read:roles
+ - create:roles
+ - delete:roles
+ - update:roles
+ - read:prompts
+ - update:prompts
+ - read:branding
+ - update:branding
\ No newline at end of file
diff --git a/articles/extensions/deploy-cli/guides/import-export-directory-structure.md b/articles/extensions/deploy-cli/guides/import-export-directory-structure.md
new file mode 100644
index 0000000000..cc16fc1cf4
--- /dev/null
+++ b/articles/extensions/deploy-cli/guides/import-export-directory-structure.md
@@ -0,0 +1,175 @@
+---
+title: Import/Export Tenant Configuration to Directory Structure
+description: Understand how the Auth0 Deploy Command Line Interface (CLI) tool works.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+# Import/Export Tenant Configuration to Directory Structure
+
+The `auth0-deploy-cli` tool includes a **directory option** that allows you to export and import an existing Auth0 tenant configuration into a predefined directory structure.
+
+::: note
+For information on how the files are expected to be laid out to work with the source control configuration utilities, see [GitHub Deployments](/extensions/github-deploy).
+:::
+
+## Import tenant configuration
+
+1. Copy `config.json.example`, making sure to replace the placeholder values with the values specific to your configuration.
+
+ ```json
+ {
+ "AUTH0_DOMAIN": ".auth0.com",
+ "AUTH0_CLIENT_ID": "",
+ "AUTH0_CLIENT_SECRET": "",
+ "AUTH0_KEYWORD_REPLACE_MAPPINGS": {
+ "AUTH0_TENANT_NAME": "",
+ "ENV": "DEV"
+ },
+ "AUTH0_ALLOW_DELETE": false,
+ "AUTH0_EXCLUDED_RULES": [
+ "rule-1-name",
+ "rule-2-name"
+ ],
+ "INCLUDED_PROPS": {
+ "clients": [ "client_secret" ]
+ },
+ "EXCLUDED_PROPS": {
+ "connections": [ "options.client_secret" ]
+ }
+ }
+ ```
+
+Use the `client ID` and secret from your newly-created client (the client is named `auth0-deploy-cli-extension` if you used the extension).
+
+By default, the tool merges with your current environment variables and overrides the `config.json` file (which has the same top key). You can use the `--no-env` option to disable the override via the command line.
+
+You can either set the environment variables, or you can place the values in a configuration file anywhere on the file system that is accessible by the CLI tool.
+
+2. Deploy using the following command:
+
+```bash
+a0deploy import --config_file config.json --input_file .
+```
+
+### Example: configuration file
+
+Here is an example of a `config.json` file:
+
+```json
+{
+ "AUTH0_DOMAIN": "",
+ "AUTH0_CLIENT_SECRET": "",
+ "AUTH0_CLIENT_ID": "",
+ "AUTH0_KEYWORD_REPLACE_MAPPINGS": {
+ "YOUR_ARRAY_KEY": [
+ "http://localhost:8080",
+ "https://somedomain.com"
+ ],
+ "YOUR_STRING_KEY": "some environment specific string"
+ },
+ "AUTH0_ALLOW_DELETE": false,
+ "INCLUDED_PROPS": {
+ "clients": [ "client_secret" ]
+ },
+ "EXCLUDED_PROPS": {
+ "connections": [ "options.client_secret" ]
+ },
+ "AUTH0_EXCLUDED_RULES": [ "auth0-account-link-extension" ],
+ "AUTH0_EXCLUDED_CLIENTS": [ "auth0-account-link" ],
+ "AUTH0_EXCLUDED_RESOURCE_SERVERS": [ "SSO Dashboard API" ],
+ "AUTH0_EXCLUDED_DEFAULTS": ["emailProvider"]
+}
+```
+
+## Export tenant configuration
+
+To export your current tenant configuration, run a command that's similar to:
+
+`a0deploy export --config_file config.json --format directory --output_folder path/to/export`
+
+<%= include('../_includes/_strip-option') %>
+
+<%= include('../_includes/_limitations') %>
+
+For more information, see [Environment Variables and Keyword Mappings](/extensions/deploy-cli/references/environment-variables-keyword-mappings).
+
+### Directory structure example
+
+Here is a sample of what the export directory structure looks like (for full details on everything that can be included, please refer to the [extension's repository](https://github.com/auth0/auth0-deploy-cli/tree/master/examples/directory):
+
+```
+repository =>
+ clients
+ client1.json
+ client2.json
+ connections
+ connection1.json
+ database-connections
+ connection1
+ database.json
+ create.js
+ delete.js
+ get_user.js
+ login.js
+ verify.js
+ emails
+ provider.json
+ verify_email.json
+ verify_email.html
+ welcome_email.json
+ welcome_email.html
+ grants
+ grant1.json
+ pages
+ login.html
+ login.json
+ password_reset.html
+ password_reset.json
+ resource-servers
+ resource_server1.json
+ resource_server2.json
+ rules
+ rule1.js
+ rule1.json
+ rule2.js
+ rules-configs
+ env_param1.json
+ some_secret1.json
+ hooks
+ hook1.js
+ hook1.json
+ guardian
+ factors
+ sms.json
+ email.json
+ otp.json
+ push-notification.json
+ provider
+ sms-twilio.json
+ templates
+ sms.json
+```
+
+::: note
+To add hook secrets to your environment, add secrets in the .json configuration file (in this example, hook1.json) as follows:
+
+```json
+"secrets": {
+ "api-key": "my custom api key"
+}
+```
+
+The `secrets` object cannot be nested, so remember to prefix your secrets.
+:::
+
+## Keep reading
+
+* [Incorporate Deploy CLI into Build Environment](/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment)
+* [Call Deploy CLI Tool Programmatically](/extensions/deploy-cli/guides/call-deploy-cli-programmatically)
+* [Deploy CLI Tool Options](/extensions/deploy-cli/references/deploy-cli-options)
+* [Import/Export Tenant Configuration to a YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
+* [Troubleshooting Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
diff --git a/articles/extensions/deploy-cli/guides/import-export-yaml-file.md b/articles/extensions/deploy-cli/guides/import-export-yaml-file.md
new file mode 100644
index 0000000000..e66ab2e842
--- /dev/null
+++ b/articles/extensions/deploy-cli/guides/import-export-yaml-file.md
@@ -0,0 +1,272 @@
+---
+title: Import/Export Tenant Configuration to YAML File
+description: Learn how to use the YAML option of the Auth0-deploy-cli tool.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+# Import/Export Tenant Configuration to YAML File
+
+The `auth0-deploy-cli` tool's **YAML option** supports the exporting to and importing of an Auth0 tenant configuration using a [YAML](http://yaml.org/) file. You can find an [example config file and other examples of using `auth0-deploy-cli`](https://github.com/auth0/auth0-deploy-cli/) in the Github repo.
+
+## Import tenant configuration
+
+To import an Auth0 tenant configuration:
+
+1. Copy `config.json.example`, making sure to replace the placeholder values with the values specific to your configuration.
+
+ ```json
+ {
+ "AUTH0_DOMAIN": ".auth0.com",
+ "AUTH0_CLIENT_ID": "",
+ "AUTH0_CLIENT_SECRET": "",
+ "AUTH0_KEYWORD_REPLACE_MAPPINGS": {
+ "AUTH0_TENANT_NAME": "",
+ "ENV": "DEV"
+ },
+ "AUTH0_ALLOW_DELETE": false,
+ "AUTH0_EXCLUDED_RULES": [
+ "rule-1-name",
+ "rule-2-name"
+ ],
+ "INCLUDED_PROPS": {
+ "clients": [ "client_secret" ]
+ },
+ "EXCLUDED_PROPS": {
+ "connections": [ "options.client_secret" ]
+ }
+ }
+ ```
+
+ Use the `client ID` and secret from your newly-created client (the client is named `auth0-deploy-cli-extension` if you used the extension).
+
+ By default, the tool merges with your current environment variables and overrides the `config.json` file (which has the same top key). You can use the `--no-env` option to disable the override via the command line.
+
+ You can either set the environment variables, or you can place the values in a configuration file anywhere on the file system that is accessible by the CLI tool.
+
+2. Deploy using the following command:
+
+ ```bash
+ a0deploy import --config_file config.json --input_file tenant.yaml
+ ```
+
+### Example: configuration file
+
+Here is the example of a `config.json` file:
+
+```json
+{
+ "AUTH0_DOMAIN": "",
+ "AUTH0_CLIENT_SECRET": "",
+ "AUTH0_CLIENT_ID": "",
+ "AUTH0_KEYWORD_REPLACE_MAPPINGS": {
+ "YOUR_ARRAY_KEY": [
+ "http://localhost:8080",
+ "https://somedomain.com"
+ ],
+ "YOUR_STRING_KEY": "some environment specific string"
+ },
+ "AUTH0_ALLOW_DELETE": false,
+ "INCLUDED_PROPS": {
+ "clients": [ "client_secret" ]
+ },
+ "EXCLUDED_PROPS": {
+ "connections": [ "options.client_secret" ],
+ "emailProvider": ["name", "credentials", "default_from_address", "enabled"]
+ },
+ "AUTH0_EXCLUDED_RULES": [ "auth0-account-link-extension" ],
+ "AUTH0_EXCLUDED_CLIENTS": [ "auth0-account-link" ],
+ "AUTH0_EXCLUDED_RESOURCE_SERVERS": [ "SSO Dashboard API" ],
+ "AUTH0_EXCLUDED_DEFAULTS": ["emailProvider"]
+}
+```
+
+### Import configuration example
+
+The following is an example of an import config file called `tenant.yaml` (for full details on everything that can be included, please refer to the [extension's repository](https://github.com/auth0/auth0-deploy-cli/tree/master/examples/directory):
+
+```yaml
+tenant:
+ # Any tenant settings can go here https://auth0.com/docs/api/management/v2#!/Tenants/get_settings
+ friendly_name: 'Auth0 Deploy Example'
+
+pages:
+ - name: "login"
+ html: "pages/login.html"
+
+ - name: "password_reset"
+ html: "pages/password_reset.html"
+
+ - name: "guardian_multifactor"
+ html: "pages/guardian_multifactor.html"
+ enabled: false
+
+ - name: "error_page"
+ html: "pages/error_page.html"
+
+clients:
+ -
+ name: "My SPA"
+ app_type: "spa"
+ # Add other client settings https://auth0.com/docs/api/management/v2#!/Clients/post_clients
+ -
+ name: "My M2M"
+ app_type: "non_interactive"
+ # Add other client settings https://auth0.com/docs/api/management/v2#!/Clients/post_clients
+
+databases:
+ - name: "users"
+ enabled_clients:
+ - "My SPA"
+ options:
+ enabledDatabaseCustomization: true
+ customScripts:
+ login: "databases/users/login.js"
+ create: "databases/users/create.js"
+ delete: "databases/users/delete.js"
+ get_user: "databases/users/get_user.js"
+ change_email: "databases/users/change_email.js"
+ change_password: "databases/users/change_password.js"
+ verify: "databases/users/verify.js"
+
+connections:
+ - name: "myad-waad"
+ strategy: "waad"
+ enabled_clients:
+ - "My SPA"
+ options:
+ tenant_domain: 'office.com'
+ client_id: 'some_client_id'
+ client_secret: 'some_client_secret'
+ domain: 'office.com'
+ waad_protocol: 'openid-connect'
+ api_enable_users: true
+ basic_profile: true
+ ext_profile: true
+ ext_groups: true
+ # Add other connection settings (https://auth0.com/docs/api/management/v2#!/Connections/post_connections)
+
+rules:
+ - name: "Common-Functions"
+ order: 10
+ script: "rules/enrich_tokens.js"
+
+rulesConfigs:
+ # Key/Value pairs for Rule configuration settings
+ - key: "SOME_SECRET"
+ value: 'some_key'
+
+hooks:
+ - name: "Client Credentials Exchange"
+ triggerId: "credentials-exchange"
+ enabled: true
+ secrets:
+ api-key: "my custom api key"
+ dependencies:
+ bcrypt: "3.0.6"
+ script: "hooks/client-credentials-exchange.js"
+
+resourceServers:
+ -
+ name: "My API"
+ identifier: "https://##ENV##.myapp.com/api/v1"
+ scopes:
+ - value: "update:account"
+ description: "update account"
+ - value: "read:account"
+ description: "read account"
+ # Add other resource server settings (https://auth0.com/docs/api/management/v2#!/Resource_Servers/post_resource_servers)
+
+emailProvider:
+ name: "smtp"
+ enabled: true
+ credentials:
+ smtp_host: "smtp.mailtrap.io"
+ smtp_port: 2525
+ smtp_user: "smtp_user"
+ smtp_pass: "smtp_secret_password"
+
+emailTemplates:
+ - template: "verify_email"
+ enabled: true
+ syntax: "liquid"
+ from: "test@email.com"
+ subject: "something"
+ body: "emails/change_email.html"
+
+ - template: "welcome_email"
+ enabled: true
+ syntax: "liquid"
+ from: "test@email.com"
+ subject: "something"
+ body: "emails/change_email.html"
+
+clientGrants:
+ - client_id: "My M2M"
+ audience: "https://##ENV##.myapp.com/api/v1"
+ scope:
+ - "update:account"
+
+guardianFactors:
+ - name: sms
+ enabled: true
+ - name: push-notification
+ enabled: true
+ - name: otp
+ enabled: true
+ - name: email
+ enabled: false
+ - name: duo
+ enabled: false
+
+guardianFactorProviders:
+ - name: sms
+ provider: twilio
+ auth_token: "some_token"
+ sid: "some_sid"
+ messaging_service_sid: "some_message_sid"
+
+guardianFactorTemplates:
+ - name: sms
+ enrollment_message: >-
+ {{code}} is your verification code for {{tenant.friendly_name}}. Please
+ enter this code to verify your enrollment.
+ verification_message: '{{code}} is your verification code for {{tenant.friendly_name}}'
+
+roles:
+ - name: Admin
+ description: App Admin
+ permissions:
+ - permission_name: 'update:account'
+ resource_server_identifier: 'https://##ENV##.myapp.com/api/v1'
+ - permission_name: 'read:account'
+ resource_server_identifier: 'https://##ENV##.myapp.com/api/v1'
+ - name: User
+ description: App User
+ permissions:
+ - permission_name: 'read:account'
+ resource_server_identifier: 'https://##ENV##.myapp.com/api/v1'
+```
+
+## Export tenant configuration
+
+To export your current tenant configuration, run a command that's similar to:
+
+`a0deploy export --config_file config.json --format yaml --output_folder path/to/export`
+
+<%= include('../_includes/_strip-option') %>
+
+<%= include('../_includes/_limitations') %>
+
+For more information, see [Environment Variables and Keyword Mappings](/extensions/deploy-cli/references/environment-variables-keyword-mappings).
+
+## Keep reading
+
+* [Incorporate Deploy CLI into Build Environment](/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment)
+* [Call Deploy CLI Tool Programmatically](/extensions/deploy-cli/guides/call-deploy-cli-programmatically)
+* [Deploy CLI Tool Options](/extensions/deploy-cli/references/deploy-cli-options)
+* [Import/Export Tenant Configuration to a Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [Troubleshooting Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
diff --git a/articles/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment.md b/articles/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment.md
new file mode 100644
index 0000000000..d535b82f6f
--- /dev/null
+++ b/articles/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment.md
@@ -0,0 +1,73 @@
+---
+title: Incorporate Deploy CLI into Build Environment
+description: Learn how to incorporate the Deploy CLI tool into your build environment.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+# Incorporate Deploy CLI into Build Environment
+
+Auth0 offers a Deploy CLI tool that we recommend you incorporate into your build system. The Deploy CLI tool allows you to:
+
+* Deploy using the command line
+* Create a repository to store your deployment configuration
+* Create a set of configuration files for each environment (e.g., development, production)
+* Have a deployment build for each environment that updates a local copy of the deployment configuration repository on your continuous integration server
+
+## Auth0 tenant layout
+
+We recommend that you have a separate Auth0 tenant/account for each environment you have. For example, you might have the following environments and Auth0 tenants:
+
+| Environment | Tenant |
+| - | - |
+| Development | *fabrikam-dev* |
+| Testing | *fabrikam-uat* |
+| Staging | *fabrikam-staging* |
+| Production | *fabrikam-prod* |
+
+### Your deploy configuration repository
+
+Your configuration repository should contain a specific set of files based on how you've chosen to import/export your tenant configuration information:
+
+* [Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
+
+You should have at least one branch for each tenant/account in your repository, which allows you to make changes without deploying them (the changes would only deploy when you merged your branch into the master, or primary, branch). With this setup, you can have a continuous integration task for each environment that automatically deploys changes to the targeted environment whenever the master branch receives updates.
+
+Your workflow would, therefore, look something like this:
+
+1. Make changes to development.
+2. Merge changes to testing (or `uat`).
+3. Test changes to `uat`. When ready, move and merge the changes to `staging`.
+4. Test `staging`. When ready, move and merge the changes to `production`.
+
+You may want to set your production environment to deploy only when triggered manually.
+
+### Your continuous integration (CI) server configuration
+
+Your CI server should have a different deploy task and config for each environment. Since each tenant/account needs to have the `auth0-deploy-cli-extension` installed and using a different domain, client ID, and secret, you will need to create individual configurations -- this has the bonus of helping you avoid accidental deployments to the wrong environment.
+
+The deploy task should do the following:
+
+ 1. Update the local repo to include the latest changes (each environment should have its own branch of the repository that can later be merged with other branches)
+ 1. If there are changes, call `a0deploy`.
+ 1. Run a suite of tests to confirm configuration is working.
+ 1. (Optional) Merge to next branch (e.g. `development` to `uat` or `uat` to `staging`.
+
+### Use keyword mappings to handle differences between the environments
+
+You should not have to store differences between environments in the Deploy Configuration Repository. Use the keyword mappings to allow the repository to be environment agnostic, and save the differences in the separate `config.json` files for each environment on the CI server.
+
+For more information, see [Environment Variables and Keyword Mappings](/extensions/deploy-cli/references/environment-variables-keyword-mappings).
+
+## Keep reading
+
+* [Install the Deploy CLI Tool](/extensions/deploy-cli/guides/install-deploy-cli)
+* [Call Deploy CLI Tool Programmatically](/extensions/deploy-cli/guides/call-deploy-cli-programmatically)
+* [Deploy CLI Tool Options](/extensions/deploy-cli/references/deploy-cli-options)
+* [Import/Export Tenant Configuration to a Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [Import/Export Tenant Configuration to a YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
+* [Troubleshooting Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
diff --git a/articles/extensions/deploy-cli/guides/install-deploy-cli.md b/articles/extensions/deploy-cli/guides/install-deploy-cli.md
new file mode 100644
index 0000000000..fd08de5bcf
--- /dev/null
+++ b/articles/extensions/deploy-cli/guides/install-deploy-cli.md
@@ -0,0 +1,81 @@
+---
+title: Install and Configure the Deploy CLI Tool
+description: Learn how to install and configure the Deploy CLI tool.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+# Install and Configure the Deploy CLI Tool
+
+This guide will show you how to install the Deploy CLI tool and configure it using the Deploy CLI extension. To do this, you must:
+
+1. [Install the Deploy CLI Tool](#install-the-deploy-cli-tool)
+2. [Install the Deploy CLI Extension](#install-the-deploy-cli-extension)
+3. [Configure the Deploy CLI Tool](#configure-the-deploy-cli-tool)
+4. [Run the Deploy CLI Tool](#run-the-deploy-cli-tool)
+
+You can also upgrade from a previous version of the tool. The `auth0-deploy-cli` tool was completely rewritten from version 1 to [version 2 or later](/extensions/deploy-cli/references/whats-new), which means that it is not backwards compatible. Please consider the following when upgrading:
+
+- The directory structure and format has changed to allow for additional object types.
+- The command line parameters have changed to allow for additional options, such as export.
+
+## Install the Deploy CLI Tool
+
+To install the Deploy CLI Tool, use the command-line interface to run:
+
+```bash
+npm i -g auth0-deploy-cli
+```
+
+## Install the Deploy CLI Extension
+
+The Deploy CLI tool must be authorized to call the Management API. To do this, the **Auth0 Deploy CLI** extension configures your tenant by creating and configuring an application named **auth0-deploy-cli-extension** and authorizing it for use with the Management API. Later, you will use the Client ID and Secret from this application to configure the Deploy CLI Tool.
+
+1. Navigate to the [Extensions](${manage_url}/#/extensions) page in the [Auth0 Dashboard](${manage_url}), locate the **Auth0 Deploy CLI** extension, and click the extension.
+
+
+
+2. Click **Install**.
+
+
+
+3. From the list of installed extensions, click **Auth0 Deploy CLI**, then click **Accept** to consent to allow the extension to access your data.
+
+::: note
+If necessary, you can also [manually create and configure the **auth0-deploy-cli-extension** application](/extensions/deploy-cli/guides/create-deploy-cli-application-manually#create-the-initial-deploy-cli-application) and [manually modify required scopes](/extensions/deploy-cli/guides/create-deploy-cli-application-manually#modify-deploy-cli-application-scopes).
+:::
+
+## Configure the Deploy CLI Tool
+
+To configure the Deploy CLI tool to use the Deploy CLI application, create a **config.json** file, including the **Client ID** and **Client Secret** from the **auth0-deploy-cli-extension** application. You can find this application on the [Applications](${manage_url}/#/applications) page in the [Auth0 Dashboard](${manage_url}).
+
+```json
+{
+ "AUTH0_DOMAIN": "${account.namespace}",
+ "AUTH0_CLIENT_ID": "${account.clientId}",
+ "AUTH0_CLIENT_SECRET": "YOUR_CLIENT_SECRET",
+ "AUTH0_KEYWORD_REPLACE_MAPPINGS": { "AUTH0_TENANT_NAME": "${account.tenant}" },
+ "AUTH0_ALLOW_DELETE": false,
+ "AUTH0_EXCLUDED_RULES": [ "rule-1-name" ]
+}
+```
+
+## Run the Deploy CLI Tool
+
+To run the Deploy CLI Tool, use the command-line interface to run:
+
+```bash
+a0deploy export --config_file config.json --format yaml --output_folder
+```
+
+## Keep reading
+
+* [Incorporate Deploy CLI into Build Environment](/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment)
+* [Call Deploy CLI Tool Programmatically](/extensions/deploy-cli/guides/call-deploy-cli-programmatically)
+* [Deploy CLI Tool Options](/extensions/deploy-cli/references/deploy-cli-options)
+* [Import/Export Tenant Configuration to a Directory Structure](extensions/deploy-cli/guides/import-export-directory-structure)
+* [Import/Export Tenant Configuration to a YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
+* [Troubleshooting the Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
diff --git a/articles/extensions/deploy-cli/index.md b/articles/extensions/deploy-cli/index.md
new file mode 100644
index 0000000000..627f5ead21
--- /dev/null
+++ b/articles/extensions/deploy-cli/index.md
@@ -0,0 +1,91 @@
+---
+title: Deploy CLI Tool
+description: Understand how the Auth0 Deploy CLI tool works.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - index
+useCase: extensibility-extensions
+---
+# Deploy CLI Tool
+
+Auth0 supports continuous integration and deployment (CI/CD) of Auth0 tenants through our [source control extensions](/extensions#deploy-hosted-pages-rules-and-database-connections-scripts-from-external-repositories) and integration into existing CI/CD pipelines using the Deploy CLI tool.
+
+The Deploy CLI tool (`auth0-deploy-cli`) supports two methods to import and export the following Auth0 tenant configuration objects:
+
+- Tenant settings
+- Rules (including secrets/settings)
+- Hooks
+- Hook Secrets
+- Connections
+- Custom databases
+- Clients/applications
+- Resource servers (APIs)
+- Pages
+- Email templates and providers
+- Guardian settings
+
+You can export the data to a predefined [directory structure](/extensions/deploy-cli/guides/import-export-directory-structure) or a [YAML configuration file](/extensions/deploy-cli/guides/import-export-yaml-file). You can call the tool [programmatically](/extensions/deploy-cli/guides/call-deploy-cli-programmatically). You can also use the tool to replace environment variables.
+
+::: warning
+This tool can be destructive to your Auth0 tenant. Please ensure you have read the documentation and tested the tool on a development tenant before using it in production.
+:::
+
+## Upgrade to latest version
+
+For version 5, the `auth0-deploy-cli` tool was updated to add support for Node.js v14 and drop support for Node.js versions earlier than v8.
+
+If you are upgrading `auth0-deploy-cli` from versions earlier than v4, please upgrade the **Auth0 Deploy CLI** extension by following the instructions for [Deploy CLI Tool v4](#deploy-cli-tool-v4) below.
+
+## Previous versions
+
+Features released in previous versions of the Deploy CLI Tool are listed below. For a complete list of changes, see the [changelog](https://github.com/auth0/auth0-deploy-cli/blob/master/CHANGELOG.md).
+
+
+### Deploy CLI Tool v4
+
+For version 4, the `auth0-deploy-cli` tool was updated to add support for Hooks and Hook Secrets.
+
+<%= include('./_includes/_upgrade-v4') %>
+
+
+### Deploy CLI Tool v3
+
+For version 3, the `auth0-deploy-cli` tool was updated to include the following changes.
+
+- Added options to the config:
+ - INCLUDED_PROPS: Enables export of properties that are excluded by default (e.g., client_secret)
+ - EXCLUDED_PROPS: Provides ability to exclude any unwanted properties from exported objects
+- Removed `--strip` option from `export` command. IDs will now be stripped by default; to override, use `--export_ids` or `AUTH0_EXPORT_IDENTIFIERS: true`.
+
+### Deploy CLI Tool v2
+
+For version 2, the `auth0-deploy-cli` tool was updated to include the following changes.
+
+- Added YAML support
+- Added support for export (deprecation of separate auth0 dump tool)
+- Delete support - The tool will, if configured via `AUTH0_ALLOW_DELETE`, delete objects if does not exist within the deploy configuration.
+- Support for additional Auth0 objects
+ - Connections including Social, Enterprise and Passwordless configurations.
+ - Improved support for database connections and associated configuration.
+ - Email Templates
+ - Email Provider
+ - Client Grants
+ - Rule Configs (Import Only)
+ - Guardian config
+ - Better support for pages
+ - Tenant level settings
+- Added support to be called programmatically
+- Improved logging
+- To simplify the tool the slack hook was removed. You can invoke the tool programmatically to support calling your own hooks
+- Support referencing clients by their name vs client_id (automatic mapping during export/import)
+- Simplified to support future Auth0 object types
+
+### Keep reading
+
+* [Install the Deploy CLI Tool](/extensions/deploy-cli/guides/install-deploy-cli)
+* [Incorporate Deploy CLI into Build Environment](/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment)
+* [Deploy CLI Tool Options](/extensions/deploy-cli/references/deploy-cli-options)
+* [Environment Variables and Keyword Mappings](/extensions/deploy-cli/references/environment-variables-keyword-mappings)
+* [Troubleshooting Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
diff --git a/articles/extensions/deploy-cli/references/deploy-cli-options.md b/articles/extensions/deploy-cli/references/deploy-cli-options.md
new file mode 100644
index 0000000000..0e11c2e000
--- /dev/null
+++ b/articles/extensions/deploy-cli/references/deploy-cli-options.md
@@ -0,0 +1,43 @@
+---
+title: Deploy CLI Options
+description: Describes the Auth0 Deploy CLI tool options.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - index
+ - concept
+useCase: extensibility-extensions
+---
+# Deploy CLI Options
+
+The following options are supported by the Deploy CLI tool `a0deploy`.
+
+## Commands
+
+- `a0deploy import` Deploy Configuration
+- `a0deploy export` Export Auth0 Tenant Configuration
+
+## Options
+- `--help` Show help `[boolean]`
+- `--version` Show version number `[boolean]`
+- `--debug, -d` Dump extra debug information. `[string] [default: false]`
+- `--proxy_url, -p` A url for proxying requests, only set this if you are behind a proxy. `[string]`
+
+## Examples
+
+```
+ a0deploy export --config_file config.json --strip --format yaml --output_folder path/to/export Dump Auth0 config to folder in YAML format
+ a0deploy export --config_file config.json --strip --format directory --output_folder path/to/export Dump Auth0 config to folder in directory format
+ a0deploy import --config_file config.json --input_file tenant.yaml Deploy Auth0 via YAML
+ a0deploy import --config_file config.json --input_file path/to/files Deploy Auth0 via Path
+```
+
+## Keep reading
+
+* [Install the Deploy CLI Tool](/extensions/deploy-cli/guides/install-deploy-cli)
+* [Incorporate Deploy CLI into Build Environment](/extensions/deploy-cli/guides/incorporate-deploy-cli-into-build-environment)
+* [Import/Export Tenant Configuration to a Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [Import/Export Tenant Configuration to a YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
+* [Call Deploy CLI Tool Programmatically](/extensions/deploy-cli/guides/call-deploy-cli-programmatically)
+* [Troubleshooting Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
diff --git a/articles/extensions/deploy-cli/references/environment-variables-keyword-mappings.md b/articles/extensions/deploy-cli/references/environment-variables-keyword-mappings.md
new file mode 100644
index 0000000000..6aba3d3e09
--- /dev/null
+++ b/articles/extensions/deploy-cli/references/environment-variables-keyword-mappings.md
@@ -0,0 +1,70 @@
+---
+title: Environment Variables and Keyword Mappings
+description: Describes environmental variables and keyword mappings for exporting tenant configurations.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - reference
+useCase: extensibility-extensions
+---
+# Environment Variables and Keyword Mappings
+
+The mappings allow you to do the following:
+
+* Use the same configuration file for all of your environments (e.g. dev, uat, staging, and prod).
+
+* Replace certain values in your configuration repo with environment-specific values. There are two ways to use the keyword mappings: You can either wrap the key in `@@key@@` or `##key##`.
+
+ - If you use the `@` symbols, it will do a `JSON.stringify` on your value before replacing it. So if it is a string, it will add quotes. and if it is an array or object, it will add braces.
+
+ - If you use the `#` symbol instead, it will just do a literal replacement; it will not add quotes or brackets.
+
+::: note
+By default the tool also merges your current environment variables and overrides the **AUTH0_KEYWORD_REPLACE_MAPPINGS** which have the same top key. You can disable this via the command line with the `--no-env` option.
+:::
+
+For example, you could specify a different JWT timeout in your dev environment, and then use prod for testing and a different environment URL.
+
+See the examples below.
+
+## `Client.json`
+
+```json
+{
+ ...
+ "callbacks": [
+ "##ENVIRONMENT_URL##/auth/callback"
+ ],
+ "jwt_configuration": {
+ "lifetime_in_seconds": ##JWT_TIMEOUT##,
+ "secret_encoded": true
+ }
+ ...
+}
+```
+
+## Dev `Config.json`
+
+```json
+"AUTH0_KEYWORD_REPLACE_MAPPINGS": {
+ "ENVIRONMENT_URL": "http://dev.fabrikam.com",
+ "JWT_TIMEOUT": 120,
+ ...
+}
+```
+
+## Prod `Config.json`
+
+```json
+"AUTH0_KEYWORD_REPLACE_MAPPINGS": {
+ "ENVIRONMENT_URL": "http://fabrikam.com",
+ "JWT_TIMEOUT": 3600,
+ ...
+}
+```
+
+## Keep reading
+
+* [Import/Export Tenant Configuration to a Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [Import/Export Tenant Configuration to a YAML file](/extensions/deploy-cli/guides/import-export-yaml-file)
diff --git a/articles/extensions/deploy-cli/references/troubleshooting.md b/articles/extensions/deploy-cli/references/troubleshooting.md
new file mode 100644
index 0000000000..935ad27372
--- /dev/null
+++ b/articles/extensions/deploy-cli/references/troubleshooting.md
@@ -0,0 +1,30 @@
+---
+title: Troubleshoot the Deploy CLI Tool
+description: Describes troubleshooting information for the Auth0 Deploy Command Line Interface (CLI) tool.
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - index
+ - concept
+useCase: extensibility-extensions
+---
+# Troubleshoot the Deploy CLI tool
+
+## Warning log entries after a Google Apps connection is recreated
+
+**Symptoms**: you see warnings in the logs with messages like `Unable to get extended attributes: unauthorized` or `Unable to get groups: unauthorized`.
+
+When you first create a Google Apps connection and enable one of the checkboxes to get extended information about the user, you'll need to go through a consent flow by having a Google Apps administrator follow the link under the "Setup instructions" button next to the connection. After completing this flow, some token information is stored on the connection's `options` object that is used to retrieve extended information when a user logs in.
+
+If you have a Google Apps connection, you'll need to ensure that the consent flow is completed before exporting the connection information using the CLI. By doing this, the necessary tokens will be included in the exported script and the administrator won't have to go through the consent flow every time the connection is recreated.
+
+::: warning
+The tokens stored in the connection's `options` object is sensitive information that should be treated securely as any other system credential.
+:::
+
+## Keep reading
+
+* [Deploy CLI Tool Overview](/extensions/deploy-cli)
+* [Import/Export Tenant Configuration to a Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [Import/Export Tenant Configuration to a YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
diff --git a/articles/extensions/deploy-cli/references/whats-new.md b/articles/extensions/deploy-cli/references/whats-new.md
new file mode 100644
index 0000000000..d6126e729d
--- /dev/null
+++ b/articles/extensions/deploy-cli/references/whats-new.md
@@ -0,0 +1,72 @@
+---
+title: What's New in Deploy CLI Tool
+description: Learn about features released in new versions of the Auth0 Deploy Command Line Interface (CLI) tool.
+public: false
+topics:
+ - extensions
+ - deploy-cli
+contentType:
+ - index
+ - concept
+useCase: extensibility-extensions
+---
+# What's New in Deploy CLI Tool
+
+Features released in each version of the Deploy CLI Tool are listed below. For a complete list of changes, see the [changelog](https://github.com/auth0/auth0-deploy-cli/blob/master/CHANGELOG.md).
+
+## Deploy CLI Tool v5
+
+For version 5, the `auth0-deploy-cli` tool was updated to include the following changes.
+
+- Updated dependencies and deprecated support for Node.js versions earlier than 8
+
+- Allowed excluding default values for emailProvider with `AUTH0_EXCLUDED_DEFAULTS`
+
+- For pages, fixed error when dumping error_page without html property
+
+## Deploy CLI Tool v4
+
+For version 4, the `auth0-deploy-cli` tool was updated to include the following changes.
+
+- Added support for Hooks and Hook Secrets
+
+<%= include('../_includes/_upgrade-v4') %>
+
+## Deploy CLI Tool v3
+
+For version 3, the `auth0-deploy-cli` tool was updated to include the following changes.
+
+- Added options to the config:
+ - INCLUDED_PROPS: Enables export of properties that are excluded by default (e.g., client_secret)
+ - EXCLUDED_PROPS: Provides ability to exclude any unwanted properties from exported objects
+- Removed `--strip` option from `export` command. IDs will now be stripped by default; to override, use `--export_ids` or `AUTH0_EXPORT_IDENTIFIERS: true`.
+
+## Deploy CLI Tool v2
+
+For version 2, the `auth0-deploy-cli` tool was updated to include the following changes.
+
+- Added YAML support
+- Added support for export (deprecation of separate auth0 dump tool)
+- Delete support - The tool will, if configured via `AUTH0_ALLOW_DELETE`, delete objects if does not exist within the deploy configuration.
+- Support for additional Auth0 objects
+ - Connections including Social, Enterprise and Passwordless configurations.
+ - Improved support for database connections and associated configuration.
+ - Email Templates
+ - Email Provider
+ - Client Grants
+ - Rule Configs (Import Only)
+ - Guardian config
+ - Better support for pages
+ - Tenant level settings
+- Added support to be called programmatically
+- Improved logging
+- To simplify the tool the slack hook was removed. You can invoke the tool programmatically to support calling your own hooks
+- Support referencing clients by their name vs client_id (automatic mapping during export/import)
+- Simplified to support future Auth0 object types
+
+## Keep reading
+
+* [Deploy CLI Tool Overview](/extensions/deploy-cli)
+* [Import/Export Tenant Configuration to a Directory Structure](/extensions/deploy-cli/guides/import-export-directory-structure)
+* [Import/Export Tenant Configuration to a YAML File](/extensions/deploy-cli/guides/import-export-yaml-file)
+* [Troubleshooting Deploy CLI Tool](/extensions/deploy-cli/references/troubleshooting)
diff --git a/articles/extensions/github-deploy.md b/articles/extensions/github-deploy.md
index 4ec8797d06..b12669f988 100644
--- a/articles/extensions/github-deploy.md
+++ b/articles/extensions/github-deploy.md
@@ -1,11 +1,21 @@
---
toc: true
description: The GitHub Deployments extension allows you to deploy rules and database connection scripts from GitHub to Auth0.
+topics:
+ - extensions
+ - github-deployments
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
-# Github Deployments
+# GitHub Deployments
-The **GitHub Deployments** extension allows you to deploy [rules](/rules) and database connection scripts from GitHub to Auth0. You can configure a GitHub repository, keep all your rules and database connection scripts there, and have them automatically deployed to Auth0 each time you push to your repository.
+The **GitHub Deployments** extension allows you to deploy [rules](/rules), rules configs, connections, database connection scripts, clients, client grants, resource servers, hosted pages and email templates from GitHub to Auth0. You can configure a GitHub repository, keep all your rules and database connection scripts there, and have them automatically deployed to Auth0 each time you push to your repository.
+
+::: note
+You can use the `auth0-deploy-cli` tool to export and import tenant configuration data to a directory structure or a YAML file. For more information, see [Deploy CLI Tool Overview](/extensions/deploy-cli).
+:::
## Configure the extension
@@ -15,13 +25,18 @@ To install and configure this extension, click on the __GitHub Deployments__ box
Set the following configuration variables:
-- **GITHUB_REPOSITORY**: The repository from which you want to deploy rules and database scripts. This can be either a public or private repository.
-- **GITHUB_BRANCH**: The branch that the extension will monitor for commits.
-- **GITHUB_TOKEN**: Your GitHub personal Access Token. Follow the instructions at [Creating an Access Token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/#creating-a-token) to create a token with `repo` scope.
-- **GITHUB_HOST**: The public accessible GitHub Enterprise _(version 2.11.3 and later)_ host name, no value is required when using github.com (optional).
-- **GITHUB_API_PATH**: GitHub Enterprise API path prefix, no value is required when using github.com (optional).
-- **SLACK_INCOMING_WEBHOOK_URL**: The Webhook URL for Slack, used in order to receive Slack notifications for successful and failed deployments (optional).
+* **REPOSITORY**: The repository from which you want to deploy rules and database scripts. This can be either a public or private repository.
+* **BRANCH**: The branch that the extension will monitor for commits.
+* **HOST**: The public accessible GitHub Enterprise _(version 2.11.3 and later)_ hostname, no value is required when using github.com (optional).
+* **API_PATH**: GitHub Enterprise API path prefix, no value is required when using github.com (optional).
+* **TOKEN**: Your GitHub Personal Access Token. Follow the instructions at [Creating an Access Token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/#creating-a-token) to create a token with `repo` scope.
+* **BASE_DIR**: The base directory, where all your tenant settings are stored
+* **AUTO_REDEPLOY**: If enabled, the extension redeploys the last successful configuration in the event of a deployment failure. Manual deployments and validation errors does not trigger auto-redeployment
+* **SLACK_INCOMING_WEBHOOK_URL**: The Webhook URL for Slack, used to receive Slack notifications for successful and failed deployments (optional).
+::: note
+Some of the configuration variables were changed in version **2.6.0** of this extension. If you are updating the extension from a prior version, make sure that you update your configuration accordingly.
+:::
Once you have provided this information, click **Install**.
@@ -47,19 +62,28 @@ You can find details on how to configure a webhook at [Creating Webhooks](https:
## Deployment
-Once you have setup the webhook in GitHub using the provided information, you are ready to start committing to your repository.
+Once you have set up the webhook in GitHub using the provided information, you are ready to start committing to your repository.
-With each commit you push to your configured GitHub repository, if changes were made in the `rules` or `database-connection` folders, the webhook will call the extension to initiate a deployment.
+With each commit you push to your configured GitHub repository, the webhook will call the extension to initiate a deployment if changes were made to one of these folders:
+- `clients`
+- `grants`
+- `emails`
+- `resource-servers`
+- `connections`
+- `database-connections`
+- `rules-configs`
+- `rules`
+- `pages`
-The __Deploy__ button on the **Deployments** tab of the extension allows you to manually deploy the rules and database connection scripts you already have in your GitHub repository. This is useful if you already have a repository filled with scripts that you want to deploy once you have setup the extension, or if you have accidentally deleted some scripts in Auth0 and need to redeploy the latest version of your repository.
+The __Deploy__ button on the **Deployments** tab of the extension allows you to manually deploy the rules and database connection scripts you already have in your GitHub repository. This is useful if you already have a repository filled with scripts that you want to deploy once you have set up the extension, or if you have accidentally deleted some scripts in Auth0 and need to redeploy the latest version of your repository.
::: panel-warning Deleting Rules and Scripts from GitHub
To maintain a consistent state, the extension will always do a full redeployment of the contents of these folders. Any rules or database connection scripts that exist in Auth0 but not in your GitHub repository will be __deleted__.
:::
-### Deploy database connection scripts
+### Deploy Database Connection scripts
-In order to deploy database connection scripts, you must first create a directory under `database-connections`. The name of the directory must __exactly__ match the name of your [database connection](${manage_url}/#/connections/database) in Auth0. Of course, you can create as many directories as you have database connections.
+To deploy database connection scripts, you must first create a directory under `database-connections`. The name of the directory must __exactly__ match the name of your [database connection](${manage_url}/#/connections/database) in Auth0. Of course, you can create as many directories as you have database connections.
Under the created directory, create one file for every script you want to use. The allowed scripts are:
@@ -76,22 +100,55 @@ If you enabled the migration feature, you will also need to provide the `get_use
You can find an example in [this GitHub repository](https://github.com/auth0-samples/github-source-control-integration/tree/master/database-connections/my-custom-db).
-### Deploy Hosted Pages
+#### Deploy Database Connection settings
+
+To deploy Database Connection settings, you must create `database-connections/[connection-name]/database.json`.
+
+_This will work only for Auth0 connections (`strategy === auth0`); for non-Auth0 connections use `connections`._
+
+_Support for using `settings.json` has been deprecated in favor of `database.json` since v3.1.1 of the extension and may be dropped in a future release._
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Connections/patch_connections_by_id) for more info on allowed attributes for Connections.
+
+### Deploy Connections
+
+To deploy a connection, you must create a JSON file under the `connections` directory of your GitHub repository. Example:
+
+__facebook.json__
+```json
+{
+ "name": "facebook",
+ "strategy": "facebook",
+ "enabled_clients": [
+ "my-client"
+ ],
+ "options": {}
+}
+```
+
+<%= include('./_includes/_embedded-clients-array') %>
+
+_This will work only for non-Auth0 connections (`strategy !== auth0`); for Auth0 connections, use `database-connections`._
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Connections/post_connections) for more info on allowed attributes for Connections.
+
+### Deploy Universal Login Pages
+
+The supported pages are:
-The supported hosted pages are:
- `error_page`
- `guardian_multifactor`
- `login`
- `password_reset`
-To deploy a page, you must create an HTML file under the `pages` directory of your GitHub repository. For each HTML page you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, in order to deploy an `error_page`, you would create two files:
+To deploy a page, you must create an HTML file under the `pages` directory of your GitHub repository. For each HTML page, you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, to deploy a `password_reset`, you would create two files:
```text
-your-github-repo/pages/error_page.html
-your-github-repo/pages/error_page.json
+your-github-repo/pages/password_reset.html
+your-github-repo/pages/password_reset.json
```
-To enable the page the `error_page.json` would contain the following:
+To enable the page, the `password_reset.json` would contain the following:
```json
{
@@ -99,9 +156,11 @@ To enable the page the `error_page.json` would contain the following:
}
```
+<%= include('./_includes/_use-default-error') %>
+
### Deploy rules
-In order to deploy a rule, you must first create a JavaScript file under the `rules` directory of your GitHub repository. Each rule must be in its own `.js` file.
+To deploy a rule, you must first create a JavaScript file under the `rules` directory of your GitHub repository. Each rule must be in its own JavaScript file.
For example, if you create the file `rules/set-country.js`, then the extension will create a rule in Auth0 with the name `set-country`.
@@ -109,10 +168,6 @@ For example, if you create the file `rules/set-country.js`, then the extension w
If you plan to use Source Control integration for an existing account, first rename your rules in Auth0 to the same name of the files you will be deploying to this directory.
:::
-You can mark rules as manual. In that case, the source control extension will not delete or update them. To mark a rule, navigate to the **Rules Configuration** tab of the GitHub Integration page. Toggle the **Manual Rule** switch for the rules you want to mark as manual. Click **Update Manual Rules** to save your changes.
-
-
-
You can control the rule order and status (`enabled`/`disabled`) by creating a JSON file with the same name as your JavaScript file. For this example, you would create a file named `rules/set-country.json`.
__set-country.js__
@@ -126,7 +181,7 @@ function (user, context, callback) {
```
__set-country.json__
-```javascript
+```json
{
"enabled": false,
"order": 15,
@@ -140,6 +195,157 @@ You can find examples in [this GitHub repository](https://github.com/auth0-sampl
Multiple rules of the same order are not allowed. To avoid conflicts, you can create a JSON file for each rule and assign a value for `order`. If you leave enough space between these values, re-ordering them without conflicts will be easier. For example, if you have three rules, instead of setting their order to `1`, `2`, `3`, you can set them to `10`, `20`, `30`. This way, to move the `30` rule before the `20`, you can simply change its `order` to any value between `11` and `19`.
+### Deploy Rules Configs
+
+To deploy a rule config, you must create a JSON file under the `rules-configs` directory of your GitHub repository. Example:
+
+__secret_number.json__
+```json
+{
+ "key": "secret_number",
+ "value": "42"
+}
+```
+
+### Deploy Clients
+
+To deploy a client, you must create a JSON file under the `clients` directory of your GitHub repository. Example:
+
+__my-client.json__
+```json
+{
+ "name": "my-client"
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Clients/post_clients) for more info on allowed attributes for Clients and Client Grants.
+
+### Deploy Clients Grants
+
+You can specify the client grants for each client by creating a JSON file in the `grants` directory.
+
+__my-client-api.json__
+```json
+{
+ "client_id": "my-client",
+ "audience": "https://myapp.com/api/v1",
+ "scope": [
+ "read:users"
+ ]
+}
+```
+
+<%= include('./_includes/_deployment-extension') %>
+
+### Deploy Resource Servers
+
+To deploy a resource server, you must create a JSON file under the `resource-servers` directory of your GitHub repository. Example:
+
+__my-api.json__
+```json
+{
+ "name": "my-api",
+ "identifier": "https://myapp.com/api/v1",
+ "scopes": [
+ {
+ "value": "read:users",
+ "description": "Allows getting user information"
+ }
+ ]
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Resource_Servers/post_resource_servers) for more info on allowed attributes for Resource Servers.
+
+### Deploy Email Provider
+
+To deploy an email provider, you must create `provider.json` file under the `emails` directory of your GitHub repository. Example:
+
+__provider.json__
+```json
+{
+ "name": "smtp",
+ "enabled": true,
+ "credentials": {
+ "smtp_host": "smtp.server.com",
+ "smtp_port": 25,
+ "smtp_user": "smtp_user",
+ "smtp_pass": "smtp_secret_password"
+ }
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Emails/patch_provider) for more info on allowed attributes for Email Provider.
+
+### Deploy Email Templates
+
+The supported email templates are:
+- `verify_email`
+- `reset_email`
+- `welcome_email`
+- `blocked_account`
+- `stolen_credentials`
+- `enrollment_email`
+- `mfa_oob_code`
+
+To deploy an email template, you must create an HTML file under the `emails` directory of your GitHub repository. For each HTML file, you need to create a JSON file (with the same name) with additional options for that template. For example, to deploy a `blocked_account` template, you would create two files:
+
+```text
+your-github-repo/emails/blocked_account.html
+your-github-repo/emails/blocked_account.json
+```
+
+__blocked_account.json__
+```json
+{
+ "template": "blocked_account",
+ "from": "",
+ "subject": "",
+ "resultUrl": "",
+ "syntax": "liquid",
+ "body": "./blocked_account.html",
+ "urlLifetimeInSeconds": 432000,
+ "enabled": true
+}
+```
+
+## Excluded records
+
+You can exclude the following records from the deployment process: `rules`, `clients`, `databases`, `connections` and `resourceServers`. If excluded, the records will not be modified by deployments.
+
+
+
+## Keywords Mapping
+
+Beginning with version **3.0.0**, you can use keywords mapping to manage your secrets and tenant-based environment variables.
+
+There are two ways to use the keyword mappings. You can either wrap the key using `@` symbols (e.g., `@@key@@`), or you can wrap the key using `#` symbols (e.g., `##key##`).
+
+ - If you use `@` symbols, your value will be converted from a JavaScript object or value to a JSON string.
+
+ - If you use `#` symbols, Auth0 will perform a literal replacement.
+
+This is useful for something like specifying different variables across your environments. For example, you could specify different JWT timeouts for your Development, QA/Testing, and Production environments.
+
+Refer to the snippets below for sample implementations:
+
+__Client.json__
+```json
+{
+ ...
+ "callbacks": [
+ "##ENVIRONMENT_URL##/auth/callback"
+ ],
+ "jwt_configuration": {
+ "lifetime_in_seconds": ##JWT_TIMEOUT##,
+ "secret_encoded": true
+ }
+ ...
+}
+```
+
+
+
## Track deployments
To track your deployments, navigate to the [extensions](${manage_url}/#/extensions) page, click on the row for the __GitHub Deployments__ extension, and select the __Deployments__ tab. You will see a list of all deployments, both successful and failed.
diff --git a/articles/extensions/gitlab-deploy.md b/articles/extensions/gitlab-deploy.md
index 30512c819d..48909fdc18 100644
--- a/articles/extensions/gitlab-deploy.md
+++ b/articles/extensions/gitlab-deploy.md
@@ -1,63 +1,79 @@
---
toc: true
description: The GitLab Deployments extension allows you to deploy Rules, Hosted Pages and Database Connection scripts from GitLab to Auth0.
+topics:
+ - extensions
+ - gitlab-deployments
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# GitLab Deployments
-The **GitLab Deployments** extension allows you to deploy [Rules](/rules), Database Connection scripts and hosted pages from GitLab to Auth0. You can configure a GitLab repository, keep all of your scripts there, and have them automatically deployed to Auth0 whenever you push changes to your repository.
+The **GitLab Deployments** extension allows you to deploy [rules](/rules), rules configs, connections, database connection scripts, clients, client grants, resource servers, hosted pages and email templates from GitLab to Auth0. You can configure a GitLab repository, keep all of your scripts there, and have them automatically deployed to Auth0 whenever you push changes to your repository.
-## Configure the Auth0 Extension
+## Configure the Auth0 extension
-To install and configure this extension, click on the **GitLab Deployments** box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the Auth0 Management Dashboard. The **Install Extension** window will open.
+1. To install and configure this extension, click on the **GitLab Deployments** box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the Auth0 Management Dashboard. The **Install Extension** window will open.

-Set the following configuration variables:
+2. Set the following configuration variables:
-* **GITLAB_REPOSITORY**: The name of your GitLab repository.
-* **GITLAB_BRANCH**: The branch of your GitLab repository your extension should monitor.
-* **GITLAB_URL**: The url of your GitLab instance, in case of gitlab.com use `https://gitlab.com`
-* **GITLAB_TOKEN**: The personal Access Token to your GitLab repository for this account. For details on how to configure one refer to [Configure a GitLab Token](configure-a-gitlab-token).
+* **REPOSITORY**: The name of your GitLab repository.
+* **BRANCH**: The branch of your GitLab repository your extension should monitor.
+* **URL**: The URL of your GitLab instance, in case of gitlab.com use `https://gitlab.com`
+* **TOKEN**: The personal Access Token to your GitLab repository for this account. To learn how to configure one, see [Configure a GitLab Token](#configure-a-gitlab-token).
+* **BASE_DIR**: The base directory, where all your tenant settings are stored. If you want to keep your tenant settings under `org/repo/tenant/production`, `org/repo` goes to the `REPOSITORY` and `tenant/production` - to `BASE_DIR`
+* **AUTO_REDEPLOY**: If enabled, the extension redeploys the last successful configuration in the event of a deployment failure. Manual deployments and validation errors does not trigger auto-redeployment
* **SLACK_INCOMING_WEBHOOK**: The URL used to integrate with Slack to deliver notifications.
-Once you have provided this information, click **Install**.
+::: note
+Some of the configuration variables were changed in version **2.7.0** of this extension. If you are updating the extension from a prior version, make sure that you update your configuration accordingly.
+:::
-### Configure a GitLab Token
+3. Once you have provided this information, click **Install**.
-Log in to your [GitLab](https://about.gitlab.com/) account and navigate to [Profile Settings > Access Tokens](https://gitlab.com/profile/personal_access_tokens).
+### Configure a GitLab token
-Create a new Access Token for Auth0. Make sure you copy the generated value and save it locally because you will not be able to access it again once you navigate away from this page.
+1. Log in to your [GitLab](https://about.gitlab.com/) account and navigate to [Profile Settings > Access Tokens](https://gitlab.com/profile/personal_access_tokens).
+
+2. Create a new Access Token for Auth0. Make sure you copy the generated value and save it locally because you will not be able to access it again once you navigate away from this page.
+
+::: panel-warning API access
+Make sure that you create the token with the `api` permission in Gitlab settings (this grants complete read/write access to the API). If your Gitlab token does not contain the necessary permissions, you may receive a "rejecting request of a tenant under quarantine" message because there was some uncaught error in the extension causing the Webtask context to be quarantined.
+:::

-Go back to the [Extensions](${manage_url}/#/extensions) page and set this value at the **Gitlab_Token** configuration variable.
+3. Go back to the [Extensions](${manage_url}/#/extensions) page and set this value at the **Gitlab_Token** configuration variable.
-## Authorize Access
+## Authorize access
-Navigate to the [Extensions](${manage_url}/#/extensions) page and click on the **Installed Extensions** tab.
+1. Navigate to the [Extensions](${manage_url}/#/extensions) page and click on the **Installed Extensions** tab.

-Click on the row for the **GitLab Deployments** extension. The first time you click on your installed extension, you will be asked to grant it to access your GitLab account.
+2. Click on the row for the **GitLab Deployments** extension. The first time you click on your installed extension, you will be asked to grant it to access your GitLab account.

-Once you agree, you will be directed to the **GitLab Integration** page.
+3. Once you agree, you will be directed to the **GitLab Integration** page.

-Copy the **Payload URL** and **Secret** values. You will use them in order to configure the GitLab Webhook in the next step.
+4. Copy the **Payload URL** and **Secret** values. You will use them to configure the GitLab Webhook in the next step.
## Configure the GitLab Webhook
Once you have configured your Auth0 Extension, you will need to configure the GitLab Webhook to complete the integration.
-In your GitLab Repository, click on the gear icon near the top right of the page to open the menu. Click on **Webhooks**.
+1. In your GitLab repository, click on the gear (Settings) icon. In the menu that appears, click on **Integrations**. This brings up the Webhook configuration area.

-Set the following configuration variables:
+2. Set the following configuration variables:
* **URL**: Set the value of the **Payload URL** from the previous step.
* **Secret Token**: Set the value of the **Secret** from the previous step.
@@ -66,30 +82,36 @@ Set the following configuration variables:

-Click **Add Webhook** to save your changes.
+3. Scroll down, and click **Add Webhook** to save your changes.
## Deployment
Once you have set up the webhook in GitLab using the provided information, you are ready to start committing to your repository.
-Your repository should have a predefined structure:
-- Rules are expected to be found under `rules` directory.
-- Database connections are expected to be found under `database-connections` directory.
-- Hosted pages are expected to be found under `pages` directory.
-
-With each commit you push to your configured GitLab repository, the webhook will call the extension to initiate a deployment if changes were made to these predefined directories.
+With each commit you push to your configured GitLab repository, the webhook will call the extension to initiate a deployment if changes were made to one of these folders:
+- `clients`
+- `grants`
+- `emails`
+- `resource-servers`
+- `connections`
+- `database-connections`
+- `rules-configs`
+- `rules`
+- `pages`
-The **Deploy** button on the **Deployments** tab of the extension allows you to manually deploy the Rules, Pages and Database Connection scripts that you already have in your GitLab repository. This is useful if your repository already contains items that you want to deploy once you have set up the extension or if you have accidentally deleted some scripts in Auth0 and need to redeploy the latest version of your repository.
+The **Deploy** button on the **Deployments** tab of the extension allows you to manually deploy the Rules, Pages, and Database Connection scripts that you already have in your GitLab repository. This is useful if your repository already contains items that you want to deploy once you have set up the extension or if you have accidentally deleted some scripts in Auth0 and need to redeploy the latest version of your repository.
::: panel-warning Full Deployment
-To maintain a consistent state, the extension will always do a full deployment of the contents of these folders. **Any rules, pages or database connection scripts that exist in Auth0 but not in your GitHub repository will be deleted**.
+To maintain a consistent state, the extension will always do a full deployment of the contents of these folders. **Any rules, pages, or database connection scripts that exist in Auth0 but not in your GitHub repository will be deleted**.
+
+To delete existing settings when AUTH0_ALLOW_DELETE is set to yes, corresponding folders must be present and contain configuration files; settings will not be deleted for missing folders or empty folders. We recommend setting up all configurations, since we are unable to provide data restores at this time.
:::
-### Deploy Database Connection Scripts
+### Deploy Database Connection scripts
-To deploy Database Connection scripts, you must first create a directory under `database-connections`. The name of the directory must match **exactly** the name of your [database connection](${manage_url}/#/connections/database) in Auth0. You can create as many directories as you have Database Connections.
+1. To deploy Database Connection scripts, you must first create a directory under `database-connections`. The name of the directory must match **exactly** the name of your [database connection](${manage_url}/#/connections/database) in Auth0. You can create as many directories as you have Database Connections.
-Under the created directory, create one file for each script you want to use. The allowed scripts are:
+2. Under the created directory, create one file for each script you want to use. The allowed scripts are:
- `get_user.js`
- `create.js`
@@ -102,7 +124,41 @@ For a generic Custom Database Connection, only the `login.js` script is required
You can find examples in [the Auth0 Samples repository](https://github.com/auth0-samples/github-source-control-integration/tree/master/database-connections/my-custom-db). While the samples were authored for GitHub, it will work for a GitLab integration as well.
-### Deploy Hosted Pages
+### Deploy Database Connection settings
+
+To deploy Database Connection settings, you must create `database-connections/[connection-name]/database.json`.
+
+_This will work only for Auth0 connections (`strategy === auth0`), for non-Auth0 connections use `connections`._
+
+_Support for using `settings.json` has been deprecated in favor of `database.json` since v3.1.1 of the extension and may be dropped in a future release._
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Connections/patch_connections_by_id) for more info on allowed attributes for Connections.
+
+
+
+### Deploy Connections
+
+To deploy a connection, you must create a JSON file under the `connections` directory of your GitLab repository. Example:
+
+__facebook.json__
+```json
+{
+ "name": "facebook",
+ "strategy": "facebook",
+ "enabled_clients": [
+ "my-client"
+ ],
+ "options": {}
+}
+```
+
+<%= include('./_includes/_embedded-clients-array') %>
+
+_This will work only for non-Auth0 connections (`strategy !== auth0`); for Auth0 connections, use `database-connections`._
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Connections/post_connections) for more info on allowed attributes for Connections.
+
+### Deploy hosted pages
The supported hosted pages are:
- `error_page`
@@ -110,14 +166,14 @@ The supported hosted pages are:
- `login`
- `password_reset`
-To deploy a page, you must create an HTML file under the `pages` directory of your GitLab repository. For each HTML page you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, in order to deploy an `error_page`, you would create two files:
+To deploy a page, you must create an HTML file under the `pages` directory of your GitLab repository. For each HTML page, you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, to deploy a `password_reset`, you would create two files:
```text
-your-gitlab-repo/pages/error_page.html
-your-gitlab-repo/pages/error_page.json
+your-bitbucket-repo/pages/password_reset.html
+your-bitbucket-repo/pages/password_reset.json
```
-To enable the page the `error_page.json` would contain the following:
+To enable the page, the `password_reset.json` would contain the following:
```json
{
@@ -125,9 +181,11 @@ To enable the page the `error_page.json` would contain the following:
}
```
-### Deploy Rules
+<%= include('./_includes/_use-default-error') %>
+
+### Deploy rules
-To deploy a rule, you must first create a JavaScript file under the `rules` directory of your GitLab repository. Each Rule must be in its own `.js` file.
+To deploy a rule, you must first create a JavaScript file under the `rules` directory of your GitLab repository. Each Rule must be in its own JavaScript file.
For example, if you create the file `rules/set-country.js`, the extension will create a Rule in Auth0 with the name `set-country`.
@@ -135,10 +193,6 @@ For example, if you create the file `rules/set-country.js`, the extension will c
If you plan to use source control integration for an existing account, first rename your Rules in Auth0 to match the name of the files you will be deploying to this directory.
:::
-You can mark rules as manual. In that case, the source control extension will not delete or update them. To mark a rule navigate to the *Rules Configuration* tab of the **GitLab Integration** page. Toggle the **Manual Rule** switch for the rules you want to mark as manual. Click **Update Manual Rules** to save your changes.
-
-
-
You can also control the Rule order and status (`enabled`/`disabled`) by creating a JSON file with the same name as your JavaScript file. For this example, you would create a file named `rules/set-country.json`.
__set-country.js__
@@ -152,7 +206,7 @@ function (user, context, callback) {
```
__set-country.json__
-```javascript
+```json
{
"enabled": false,
"order": 15,
@@ -162,19 +216,172 @@ __set-country.json__
You can find a `login_success` example in [the Auth0 Samples repository](https://github.com/auth0-samples/github-source-control-integration/tree/master/rules). While the sample was authored for GitHub, it will work for a GitLab integration as well.
-#### Set Rule Order
+#### Set rule order
-To avoid conflicts, you are cannot set multiple Rules of the same order. However, you can create a JSON file for each rule, and within each file, assign a value for `order`. We suggest using number values that allow for reordering with less risk for conflict. For example, assign a value of `10` to the first Rule and `20` to the second Rule, rather than using values of `1` and `2`, respectively).
+To avoid conflicts, you cannot set multiple Rules of the same order. However, you can create a JSON file for each rule, and within each file, assign a value for `order`. We suggest using number values that allow for reordering with less risk of conflict. For example, assign a value of `10` to the first Rule and `20` to the second Rule, rather than using values of `1` and `2`, respectively).
-#### Set the Stage
+#### Set the stage
-After you deploy a Rule, you cannot change its stage, or the area where the Rule executes.
+After you deploy a Rule, you cannot change its stage or the area where the Rule executes.
If you need the rule to execute in a different stage, you must create a new Rule with the updated stage and delete the original Rule.
-Please note that you may have only a single Rule for the `user_registration` and `login_failure` stages.
+::: note
+You may have only a single Rule for the `user_registration` and `login_failure` stages.
+:::
+
+### Deploy Rules Configs
+
+To deploy a rule config, you must create a JSON file under the `rules-configs` directory of your GitLab repository. Example:
+
+__secret_number.json__
+```json
+{
+ "key": "secret_number",
+ "value": 42
+}
+```
+
+### Deploy Clients
+
+To deploy a client, you must create a JSON file under the `clients` directory of your GitLab repository. Example:
+
+__my-client.json__
+```json
+{
+ "name": "my-client"
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Clients/post_clients) for more info on allowed attributes for Clients and Client Grants.
+
+### Deploy Clients Grants
+
+You can specify the client grants for each client by creating a JSON file in the `grants` directory.
+
+__my-client-api.json__
+```json
+{
+ "client_id": "my-client",
+ "audience": "https://myapp.com/api/v1",
+ "scope": [
+ "read:users"
+ ]
+}
+```
+
+<%= include('./_includes/_deployment-extension') %>
+
+### Deploy Resource Servers
+
+To deploy a resource server, you must create a JSON file under the `resource-servers` directory of your GitLab repository. Example:
+
+__my-api.json__
+```json
+{
+ "name": "my-api",
+ "identifier": "https://myapp.com/api/v1",
+ "scopes": [
+ {
+ "value": "read:users",
+ "description": "Allows getting user information"
+ }
+ ]
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Resource_Servers/post_resource_servers) for more info on allowed attributes for Resource Servers.
+
+### Deploy Email Provider
+
+To deploy an email provider, you must create `provider.json` file under the `emails` directory of your GitLab repository. Example:
+
+__provider.json__
+```json
+{
+ "name": "smtp",
+ "enabled": true,
+ "credentials": {
+ "smtp_host": "smtp.server.com",
+ "smtp_port": 25,
+ "smtp_user": "smtp_user",
+ "smtp_pass": "smtp_secret_password"
+ }
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Emails/patch_provider) for more info on allowed attributes for Email Provider.
+
+### Deploy Email Templates
+
+The supported email templates are:
+- `verify_email`
+- `reset_email`
+- `welcome_email`
+- `blocked_account`
+- `stolen_credentials`
+- `enrollment_email`
+- `mfa_oob_code`
+
+To deploy an email template, you must create an HTML file under the `emails` directory of your GitLab repository. For each HTML file, you need to create a JSON file (with the same name) with additional options for that template. For example, to deploy a `blocked_account` template, you would create two files:
+
+```text
+your-gitlab-repo/emails/blocked_account.html
+your-gitlab-repo/emails/blocked_account.json
+```
+
+__blocked_account.json__
+```json
+{
+ "template": "blocked_account",
+ "from": "",
+ "subject": "",
+ "resultUrl": "",
+ "syntax": "liquid",
+ "body": "./blocked_account.html",
+ "urlLifetimeInSeconds": 432000,
+ "enabled": true
+}
+```
+
+## Excluded records
+
+You can exclude the following records from the deployment process: `rules`, `clients`, `databases`, `connections` and `resourceServers`. If excluded, the records will not be modified by deployments.
+
+
+
+## Keywords Mapping
+
+Beginning with version **3.0.0**, you can use keywords mapping to manage your secrets and tenant-based environment variables.
+
+There are two ways to use the keyword mappings. You can either wrap the key using `@` symbols (e.g., `@@key@@`), or you can wrap the key using `#` symbols (e.g., `##key##`).
+
+ - If you use `@` symbols, your value will be converted from a JavaScript object or value to a JSON string.
+
+ - If you use `#` symbols, Auth0 will perform a literal replacement.
+
+This is useful for something like specifying different variables across your environments. For example, you could specify different JWT timeouts for your Development, QA/Testing, and Production environments.
+
+Refer to the snippets below for sample implementations:
+
+__Client.json__
+```json
+{
+ ...
+ "callbacks": [
+ "##ENVIRONMENT_URL##/auth/callback"
+ ],
+ "jwt_configuration": {
+ "lifetime_in_seconds": ##JWT_TIMEOUT##,
+ "secret_encoded": true
+ }
+ ...
+}
+```
+
+
-## Track Deployments
+## Track deployments
To track your deployments, navigate to the [Extensions](${manage_url}/#/extensions) page, click on the row for the **GitLab Deployments** extension, and select the **Deployments** tab. You will see a list of all deployments.
diff --git a/articles/extensions/index.md b/articles/extensions/index.md
index 1fe3f26f3d..fdfa06a1bd 100644
--- a/articles/extensions/index.md
+++ b/articles/extensions/index.md
@@ -1,62 +1,79 @@
---
description: Extensions enable you to install applications or run commands/scripts that extend the functionality of Auth0.
toc: true
+topics:
+ - extensions
+contentType:
+ - index
+useCase: extensibility-extensions
---
# Auth0 Extensions
-Auth0 Extensions enable you to install applications (such as [Webtasks](https://webtask.io/)) or run commands/scripts that extend the functionality of the Auth0 base product.
+Auth0 Extensions enable you to install applications or run commands/scripts that extend the functionality of the Auth0 base product.
Each extension is separate from all other extensions. Auth0 defines extensions per tenant, so data is stored by the pair `tenant\extension`.
-## Using an Extension
+## Pre-defined extensions
-Auth0 provides the following pre-defined extensions, and they are available for installation via the [Dashboard](${manage_url}). To use one or more of the following apps, you must provide the required configuration information and finish installing the extensions.
+Auth0 provides a selection of pre-defined extensions, which you can install via the [Dashboard](${manage_url}/extensions).
-
+### Authorization
-## What types of actions can I do with extensions?
+- [Auth0 Authorization Extension](/extensions/authorization-extension): Manage authorizations for users with groups, roles, and permissions. We recommend that you use our [Authorization Core](/authorization/guides/how-to) feature set instead, which is being expanded to match the functionality of the Authorization Extension and improves performance and scalability. For a comparison, see [Authorization Core vs. Authorization Extension](/authorization/concepts/core-vs-extension).
-### Manage the authorizations for Users using Groups, Roles and Permissions
-- [Auth0 Authorization Extension](/extensions/authorization-extension)
+- [Delegated Administration](/extensions/delegated-admin): Allow a select group of people to manage users without providing access to any other area of the Dashboard.
-### Easily manage custom social connections
-- [Custom Social Connections Extension](/extensions/custom-social-extensions)
+### Connections
+
+- [Custom Social Connections Extension](/extensions/custom-social-extensions): Configure and manage custom social identity providers.
+
+- [Single Sign-on (SSO) Dashboard Extension](extensions/sso-dashboard): Create a Single Sign-on (SS0) dashboard that allows users to sign into any of multiple listed enterprise applications.
+
+### Manage users
+
+- [Users Import / Export](/extensions/user-import-export): Bulk import and export database users.
+
+### Extend and integrate
+
+Use your own custom webhooks in conjunction with Auth0 APIs:
-### Go through the audit logs and call the appropriate webhook for specific API event triggers
- [Auth0 Management API Webhooks](/extensions/management-api-webhooks)
- [Auth0 Authentication API Webhooks](/extensions/authentication-api-webhooks)
-### Test various endpoints of the Auth0 Authentication API
+### Deployment and source control
+
+Keep history and deploy [rules](/rules), [database connection](/connections/database) scripts and other assets from external repositories:
+
+- [GitHub Deployments Extension](/extensions/github-deploy)
+- [Bitbucket Deployments Extension](/extensions/bitbucket-deploy)
+- [GitLab Deployments Extension](/extensions/gitlab-deploy)
+- [Visual Studio Team Services Deployments Extension](/extensions/visual-studio-team-services-deploy)
+- [Deploy CLI Tool Extension](/extensions/deploy-cli)
+
+### Troubleshoot
+
+Test Auth0 API endpoints:
+
- [Authentication API Debugger Extension](/extensions/authentication-api-debugger)
-### Monitor your AD/LDAP connectors
-- [Auth0 AD/LDAP Connector Health Monitor](/extensions/adldap-connector)
+### Monitor
+
+- [Auth0 AD/LDAP Connector Health Monitor](/extensions/adldap-connector): Monitor your [AD/LDAP Connectors](/connector/overview).
-### Import or Export existing users
-- [Users Import / Export](/extensions/user-import-export)
+- [Real-time Webtask Logs](/extensions/realtime-webtask-logs): Access real-time Webtask logs.
+
+### Logs export
+
+Export Auth0 logs to external services:
-### Export Auth0 logs to an external service
- [Auth0 Logs to Application Insights](/extensions/application-insight)
+- [Auth0 Logs to AWS Cloudwatch](/extensions/cloudwatch)
- [Auth0 Logs to Azure Blob Storage](/extensions/azure-blob-storage)
+- [Auth0 Logs to Logentries](/extensions/logentries)
- [Auth0 Logs to Loggly](/extensions/loggly)
+- [Auth0 Logs to Logstash](/extensions/logstash)
+- [Auth0 Logs to Mixpanel](/extensions/mixpanel)
- [Auth0 Logs to Papertrail](/extensions/papertrail)
- [Auth0 Logs to Sumo Logic](/extensions/sumologic)
- [Auth0 Logs to Splunk](/extensions/splunk)
-- [Auth0 Logs to Logstash](/extensions/logstash)
-- [Auth0 Logs to Mixpanel](/extensions/mixpanel)
-- [Auth0 Logs to Logentries](/extensions/logentries)
-
-### Access to real-time webtask logs
-- [Real-time Webtask Logs](/extensions/realtime-webtask-logs)
-
-### Expose the Users dashboard to a group of users without allowing them access to the dashboard
-- [Delegated Administration](/extensions/delegated-admin)
-
-### Deploy hosted pages, rules, and database connections scripts from external repositories
-- [GitHub Deployments Extension](/extensions/github-deploy)
-- [Bitbucket Deployments Extension](/extensions/bitbucket-deploy)
-- [GitLab Deployments Extension](/extensions/gitlab-deploy)
-- [Visual Studio Team Services Deployments Extension](/extensions/visual-studio-team-services-deploy)
-### Create a SSO dashboard with multiple enterprise applications
-- [SSO Dashboard Extension](extensions/sso-dashboard)
diff --git a/articles/extensions/logentries.md b/articles/extensions/logentries.md
index 277e5be9eb..b7b7f7188a 100644
--- a/articles/extensions/logentries.md
+++ b/articles/extensions/logentries.md
@@ -1,5 +1,11 @@
---
description: How to enable and use the Logentries extension.
+topics:
+ - extensions
+ - logentries
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Logs to Logentries
@@ -14,13 +20,15 @@ To install and configure this extension, click on the _Auth0 Logs to Logentries_
At this point you should set the following configuration variables:
- **Schedule**: The frequency with which logs should be exported. The schedule can be customized even further after creation.
-- **BATCH_SIZE**: The ammount of logs to be read on each execution. Maximun is 100.
+- **BATCH_SIZE**: The amount of logs to be read on each execution. Maximun is 100.
- **LOGENTRIES_TOKEN**: The Logentries Token for your log set to which the Auth0 logs will be exported.
- **LOG_LEVEL**: The minimal log level of events that you would like sent to Logentries.
- **LOG_TYPES**: The events for which logs should be exported. If you want you can send only events with a specific type (for example, failed logins).
Once you have provided this information, click the *Install* button to finish installing the extension.
+<%= include('./_includes/_batch-size') %>
+
## Retrieve the required information from Logentries
In order to acquire the *LOGENTRIES_TOKEN* information, navigate to [Logentries](https://logentries.com) and login to your account or register for a new one. From the menu on the left select *Logs > Add New Log*.
diff --git a/articles/extensions/loggly.md b/articles/extensions/loggly.md
index fe5b0b24e2..d2d5f5d778 100644
--- a/articles/extensions/loggly.md
+++ b/articles/extensions/loggly.md
@@ -1,5 +1,11 @@
---
description: How to install and configure the Auth0 Logs to Loggly Extension.
+topics:
+ - extensions
+ - loggly
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Logs to Loggly
@@ -29,6 +35,8 @@ You can find the __Global Client ID__ and __Global Client Secret__ information a
Once you have provided this information, click the *Install* button to finish installing the extension.
+<%= include('./_includes/_batch-size') %>
+
## Retrieve the required information from Loggly
Let's see how we can retrieve the __Loggly_Customer_Token__ information.
diff --git a/articles/extensions/logstash.md b/articles/extensions/logstash.md
index ff1fa04426..ba02d1b161 100644
--- a/articles/extensions/logstash.md
+++ b/articles/extensions/logstash.md
@@ -1,5 +1,11 @@
---
description: How to install and configure the Auth0 Logs to Logstash extension.
+topics:
+ - extensions
+ - logstash
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Logs to Logstash
@@ -17,7 +23,7 @@ At this point you should set the following configuration variables:
| Parameter | Description |
|:-----------------|:------------|
| **Schedule** | The frequency with which logs should be exported. The schedule can be customized even further after creation. |
-| **BATCH_SIZE** | The ammount of logs to be read on each execution. Maximun, and default, is `100`. |
+| **BATCH_SIZE** | The amount of logs to be read on each execution. Maximun, and default, is `100`. |
| **LOGSTASH_URL** Required | Your Logstash URL as defined for use with `logstash-input-http` plugin. |
| **LOGSTASH_INDEX** Required | Your Logstash Index to which the logs will be routed. |
| **LOGSTASH_TOKEN** | The token required for your Logstash deployments that will be included in the querystring. |
@@ -31,6 +37,12 @@ At this point you should set the following configuration variables:
Once you have provided this information, click the _Install_ button to finish installing the extension.
+<%= include('./_includes/_batch-size') %>
+
+### Using extension with ElasticSearch
+
+The extension is sending logs to the logstash instance as they are, including `_id`, which cannot be accepted by ElasticSearch. To fix that, you need rename `_id` to something else. You can do that by adding pipeline with `filter { mutate { rename => { "_id" => "log_id" } } }`.
+
## Use the Extension
To view all scheduled jobs, navigate to the [Extensions](${manage_url}/#/extensions) page of the [Management Portal](${manage_url}), click on the **Installed Extensions** link, and select the **Auth0 Logs to Logstash** line.
@@ -45,7 +57,7 @@ You can view more details by clicking on the job you created. In this page you c
## Replay Logs
-In the event of a Logstash failure or service interuption you can replay the logs starting from the failed log.
+In the event of a Logstash failure or service interruption you can replay the logs starting from the failed log.
To replay logs:
diff --git a/articles/extensions/management-api-webhooks.md b/articles/extensions/management-api-webhooks.md
index 88ed2f20b0..cb81a4d5e8 100644
--- a/articles/extensions/management-api-webhooks.md
+++ b/articles/extensions/management-api-webhooks.md
@@ -1,5 +1,11 @@
---
description: How to install and configure the Auth0 Management API Webhooks Extension.
+topics:
+ - extensions
+ - management-api-webhooks
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Extension: Auth0 Management API Webhooks
@@ -10,13 +16,16 @@ The Auth0 Management API Webhooks Extension allows you to use your own custom we
To complete installation of this extension, click on the Auth0 Management API Webhooks box in the list of provided extensions on the Extensions page of the Management Portal. In the "Install Extension" window that then pops open, you will be asked to provide the following configuration variables:
-- __Schedule__: The frequency with which the webhook runs;
-- __Auth0_Domain__: The domain of your Auth0 app;
-- __Auth0_Global_Client_ID__: The Auth0 Global Client ID;
-- __Auth0_Global_Client_Secret__: The Auth0 Global Client Secret;
-- __Auth0_API_Endpoints__: The specific Auth0 Management API endpoints you want to monitor/call;
-- __Webhook URL__: The URL of your webhook;
+- __Schedule__: The frequency with which the job runs
+- __Batch_Size__: The amount of logs the extension will attempt to read and send on each execution. Extension could send multiple batches per run, depending on amount of time necessary to process.
+- __Auth0_API_Endpoints__: The specific Auth0 Management API endpoints you want to monitor/call
+- __Webhook_URL__: The URL of your webhook
+- __Authorization__: String to be added as `Authorization` header.
+- __Send_as_Batch__: If enabled, the extension will send the whole batch of logs to the webhook in a single request. Otherwise, extension sends logs one-by-one to webhook. Only disable if your webhook does not support batched messages.
- __Webhook_Concurrent_Calls__: The maximum number of concurrent calls that will be made to your webhook.
+- __Start_From__: Log Checkpoint to start from.
+- __Slack_Incoming_Webhook_URL__: Extension can report statistics and possible failures to the Slack.
+- __Slack_Send_Success__: If enabled, extension will be sending messages on each run. Otherwise - only on fails.
Once you have provided the required pieces of information, click "Install" to finish installing the extension.
@@ -74,4 +83,4 @@ Here is an example of the payload that will be sent:
}
```
-<%= include('./_troubleshoot-webhooks') %>
\ No newline at end of file
+<%= include('./_troubleshoot-webhooks') %>
diff --git a/articles/extensions/mixpanel.md b/articles/extensions/mixpanel.md
index 3c5d4254b4..681af41310 100644
--- a/articles/extensions/mixpanel.md
+++ b/articles/extensions/mixpanel.md
@@ -1,42 +1,53 @@
---
description: How to configure and use the Auth0 Logs to Mixpanel extension.
+topics:
+ - extensions
+ - mixpanel
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Logs to Mixpanel
The Auth0 Logs to Mixpanel is a scheduled job that takes all of your Auth0 logs and exports them to [Mixpanel](https://mixpanel.com).
-## Configuring the Extension
+## Step 1: Get the required information from Mixpanel
-To install and configure this extension, click on the **Auth0 Logs to Mixpanel** box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the [Auth0 Dashboard](${manage_url}). The **Install Extension** window pops open.
+First you need to get some required information from Mixpanel: the Token and API Key that Auth0 will use to connect and push logs.
-
+1. Go to [Mixpanel](https://mixpanel.com)
+1. Click on your [Account Settings](https://mixpanel.com/account/)
+1. Click on the **Projects** tab
+1. Copy the **Token** and **API Key** information. These map respectively to the **MIXPANEL_TOKEN** and **MIXPANEL_KEY** variables that you will set in the next step
-At this point you should set the following configuration variables:
+
+
+## Step 2: Configure Auth0
+
+Go to [Dashboard > Extensions](${manage_url}/#/extensions) and click on the **Auth0 Logs to Mixpanel** box in the list of provided extensions.
+
+The **Install Extension** window pops open.
+
+
+
+Set the following configuration variables:
- **Schedule**: The frequency with which logs should be exported. The schedule can be customized even further after creation.
- **MIXPANEL_TOKEN**: The Mixpanel Token for your mixpanel project to which the Auth0 logs will be exported.
- **MIXPANEL_KEY**: The Mixpanel API Key for your mixpanel project to which the Auth0 logs will be exported.
-- **BATCH_SIZE**: The ammount of logs to be read on each execution. Maximun is 20.
+- **BATCH_SIZE**: The amount of logs to be read on each execution. Maximum is 20.
- **LOG_LEVEL**: The minimal log level of events that you would like sent to Mixpanel.
- **LOG_TYPES**: The events for which logs should be exported. If you want you can send only events with a specific type (for example, failed logins).
Once you have provided this information, click the **Install** button to finish installing the extension.
-## Retrieve the required information from Mixpanel
-
-In order to acquire the **MIXPANEL_TOKEN** and **MIXPANEL_KEY** information, navigate to [Mixpanel](https://mixpanel.com) and click on your [Account Settings](https://mixpanel.com/account/). Click on the **Projects** tab. You now need to copy the **Token** and **API Key** information. These map respectively to the **MIXPANEL_TOKEN** and **MIXPANEL_KEY** variables.
-
-
-
-## Using Your Installed Extension
-
-To view all scheduled jobs, navigate to the [Extensions](${manage_url}/#/extensions) page of the [Auth0 Dashboard](${manage_url}), click on the **Installed Extensions** link, and select the **Auth0 Logs to Mixpanel** line. There you can see the job you just created, modify its state by toggling the **State** switch, see when the next run is due and what was the result of the last execution.
+<%= include('./_includes/_batch-size') %>
-
+## Use your extension
-You can view more details by clicking on the job you created. In this page you can view details for each execution, reschedule, access realtime logs, and more.
+To view all jobs, navigate to [Dashboard > Extensions](${manage_url}/#/extensions), click on the **Installed Extensions** link, and select the **Auth0 Logs to Mixpanel** line. There you can see the alls job and failed jobs. You can also view the logs of these runs.
-
+You can create a cron webtask (that will run every 10 minutes) or view more details around existing cron webtasks. In the terminal, you can view details for each execution, reschedule, access realtime logs, and more.
That's it, you are done! You can now navigate to [Mixpanel](https://mixpanel.com) and view your [Auth0 Logs](${manage_url}/#/logs).
diff --git a/articles/extensions/papertrail.md b/articles/extensions/papertrail.md
index b38c4951d0..d8aef88e25 100644
--- a/articles/extensions/papertrail.md
+++ b/articles/extensions/papertrail.md
@@ -1,5 +1,11 @@
---
description: How to configure and retrieve information from the Auth0 Logs to Papertrail extension.
+topics:
+ - extensions
+ - papertrail
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Auth0 Logs to Papertrail
@@ -12,35 +18,33 @@ To install and configure this extension, click on the _Auth0 Logs to Papertrail_

-At this point you should set the following configuration variables:
+At this point, you should set the following configuration variables:
- **Schedule**: The frequency with which logs should be exported. The schedule can be customized even further after creation.
-- **BATCH_SIZE**: The ammount of logs to be read on each execution. Maximun is 100.
+- **BATCH_SIZE**: The number of logs per batch (up to a maximum of 100). Note that logs are batched before sending, with multiple batches sent each time the extension runs.
+- **START_FROM**: The Checkpoint ID of the log from which you want the extension to start sending.
+- **SLACK_INCOMING_WEBHOOK_URL**: The Incoming Webhook URL used to report statistics and events to your Slack account/channel.
+- **SLACK_SEND_SUCCESS**: If yes, enables verbose notifications to Slack. Useful for troubleshooting.
+- **LOG_LEVEL**: The minimal log level of events that you would like sent to Papertrail.
+- **LOG_TYPES**: The events for which logs should be exported.
- **PAPERTRAIL_HOST**: The destination hostname for your logs.
- **PAPERTRAIL_PORT**: The destination port for your logs.
- **PAPERTRAIL_SYSTEM**: The destination system for your logs.
-- **LOG_LEVEL**: The minimal log level of events that you would like sent to Papertrail;
-- **LOG_TYPES**: The events for which logs should be exported.
Once you have provided this information, click the *Install* button to finish installing the extension.
-## Retrieve the required information from Papertrail
-
-In order to configure a new system for Auth0 logs and acquire the *PAPERTRAIL_HOST* and *PAPERTRAIL_PORT* information, follow the next steps:
-1. Login to [Papertrail](https://papertrailapp.com) and navigate to your [Dashboard](https://papertrailapp.com/dashboard).
-2. Click the *Add Systems* button.
+<%= include('./_includes/_batch-size') %>
-
+## Retrieve the required information from Papertrail
-3. Your log destination is created! Copy the URL and Port information displayed with the message *Your systems & apps will log to*. These map respectively to the *PAPERTRAIL_HOST* and *PAPERTRAIL_PORT* variables.
+To configure a new system for Auth0 logs and acquire the *PAPERTRAIL_HOST* and *PAPERTRAIL_PORT* information:
-
+1. Login to [Papertrail](https://papertrailapp.com). You'll be directed to the **quick start and tour** page.
+2. Click the *Add your first system* button.
-If you already have a system you want to use, follow the next steps:
-1. Login to [Papertrail](https://papertrailapp.com) and navigate to your [Settings > Log Destinations](https://papertrailapp.com/account/destinations).
-2. Locate the system you want to use and copy the URL and Port information. These map respectively to the *PAPERTRAIL_HOST* and *PAPERTRAIL_PORT* variables.
+You'll get redirected again, and at the top of the page, you will see a message that says something like **Your logs will go to logs4.papertrailapp.com:12345 and appear in Events.**. The log destination displayed is where your logs will go. The log and port information map to the *PAPERTRAIL_HOST* (i.e., `logs4.papertrailapp.com`) and *PAPERTRAIL_PORT* (i.e., `12345`) variables Auth0 asked for, respectively.
-
+Per Papertrail, "no explicit configuration is required...just start sending logs. When Papertrail receives a message from a hostname that is not already present in your account, the system will be automatically added."
## Using Your Installed Extension
@@ -48,16 +52,12 @@ If you already have a system you want to use, follow the next steps:

-You can view more details by clicking on the job you created. In this page you can view details for each execution, reschedule, access realtime logs, and more.
+You can view more details by clicking on the job you created. In this page, you can view details for each execution, reschedule, access realtime logs, and more.

-That's it, you are done! You can now navigate to [Papertrail](https://papertrailapp.com) and view your [Auth0 Logs](${manage_url}/#/logs), by selecting the configured system.
-
-
+That's it, you are done! You can now navigate to [Papertrail](https://papertrailapp.com) and view your [Auth0 Logs](${manage_url}/#/logs) under **Events**.
::: note
-You may have noticed that we didn't set a value for *PAPERTRAIL_SYSTEM*. This variable, when not set by the user, takes the default value of `auth0-logs`. As you can see in the previous screenshot, this is how our system will be displayed in the Papertrail dashboard.
+You may have noticed that we didn't set a value for *PAPERTRAIL_SYSTEM*. This variable, when not set by the user, takes the default value of `auth0-logs`. This is how Auth0's logs will be displayed and referred to in the Papertrail dashboard.
:::
-
-
diff --git a/articles/extensions/realtime-webtask-logs.md b/articles/extensions/realtime-webtask-logs.md
index 5cd0e514c2..7aa762f9c7 100644
--- a/articles/extensions/realtime-webtask-logs.md
+++ b/articles/extensions/realtime-webtask-logs.md
@@ -1,12 +1,18 @@
---
description: How to configure, use debug rules using the Real-time Webtask Logs extension.
+topics:
+ - extensions
+ - realtime-webtask-logs
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Real-time Webtask Logs
-_Real-time Webtask Logs_ is an extension that displays all logs in real-time for all custom code in your account. This includes all `console.log` output and exceptions.
+_Real-time Webtask Logs_ is an extension that displays all logs in real-time for the custom code in your account. This includes all `console.log` output and exceptions.
-## Configuring the Extension
+## Configuring the extension
To install and configure this extension, click on the _Real-time Webtask Logs_ box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the [Management Portal](${manage_url}). The _Install Extension_ window pops open.
@@ -14,15 +20,23 @@ To install and configure this extension, click on the _Real-time Webtask Logs_ b
Click the _Install_ button.
-## Using Your Installed Extension
+## Using your installed extension
To view your installed extension, navigate to the [Extensions](${manage_url}/#/extensions) page of the [Management Portal](${manage_url}), click on the _Installed Extensions_ link, and select the _Real-time Webtask Logs_ line. You can view the logs in full screen by selecting the _FULL SCREEN MODE_ button. Press `Escape` to exit full screen mode.

-To clear the logs and start fresh select the the red _CLEAR CONSOLE_ button at the bottom right.
+To clear the logs and start fresh select the red _CLEAR CONSOLE_ button at the bottom right.
-## Debugging Rules
+## Secure logging
+
+Because the Webtask Logs extension uses the users request, logging sensitive information is a concern of which you should be mindful.
+
+For example, your custom database scripts work with the `user` object extensively. The `user` object may contain sensitive information, and logging the complete object may lead to its disclosure to the Webtask Logs extension.
+
+Obviously, Auth0 strongly discourages such practices. These actions could lead to the disclosure of your users' sensitive information. **We caution you to be aware of the objects that you log and to ensure sensitive information is not logged**
+
+## Debugging rules
The _Real-time Webtask Logs_ extension can be used to debug any [Rules](/rules) in your implementation. This includes all `console.log` output and exceptions. Let's follow a simple _hello world_ example.
@@ -42,8 +56,6 @@ You are now ready to run this rule. Before you do so, open a new tab and navigat

-That's it, you are done!
-
## Additional Information
- [Rules debugging](/rules#debugging)
- [Real-time Auth0 Webtask Logs GitHub repository](https://github.com/auth0/auth0-extension-realtime-logs)
diff --git a/articles/extensions/segment.md b/articles/extensions/segment.md
new file mode 100644
index 0000000000..3c47b20290
--- /dev/null
+++ b/articles/extensions/segment.md
@@ -0,0 +1,54 @@
+---
+description: How to install and configure the Auth0 Logs to Segment Extension.
+topics:
+ - extensions
+ - segment
+contentType:
+ - how-to
+useCase: extensibility-extensions
+---
+# Auth0 Logs to Segment
+
+The *Auth0 Logs to Segment* is a scheduled job that takes all of your Auth0 logs and exports them to [Segment](https://www.segment.com/).
+
+## Configure the Extension
+
+To install and configure this extension, click on the __Auth0 Logs to Segment__ box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the [dashboard](${manage_url}). The __Install Extension__ window pops open.
+
+At this point you should set the following configuration variables:
+
+| Parameter | Description |
+|:-----------------|:------------|
+| **Schedule** | The frequency with which logs should be exported. The schedule can be customized even further after creation. |
+| **BATCH_SIZE** | The amount of logs to be read on each execution. Maximun, and default, is `100`. |
+| **START_FROM** | The checkpoint ID of the log from where you want to start. |
+| **SLACK_INCOMING_WEBHOOK** | The Slack incoming webhook URL used to send relevant updates. |
+| **SLACK_SEND_SUCCESS** | Toggle for sending verbose notifications to Slack. |
+| **SEGMENT_KEY** | Your segment key. |
+
+Once you have provided this information, click the _Install_ button to finish installing the extension.
+
+<%= include('./_includes/_batch-size') %>
+
+## Use the Extension
+
+You can monitor activity by logging into the extension. There you can find reports on most recent runs. Reports contains amount of logs processed and errors, if any.
+
+## Replay Logs
+
+In the event of a Segment failure or service interruption you can replay the logs starting from the failed log.
+
+To replay logs:
+
+1. Get the checkpoint ID of the failed log.
+2. Go to the Auth0 Logs to Segment extension settings.
+3. Enter the checkpoint in the **START_FROM** field.
+4. Click the **Save** button to replay the failed logs.
+
+## Slack Integration
+
+To set up [Slack](https://slack.com/) integration, provide an [Incoming Webhook URL](https://api.slack.com/incoming-webhooks) to the **SLACK_INCOMING_WEBHOOK** field in the Auth0 Logs to Segment [extension settings](${manage_url}/#/extensions).
+
+The extension sends failed transaction notifications to Slack with the checkpoint code displayed in the message. You can also enable verbose notifications by turning on the `SLACK_SEND_SUCCESS` setting.
+
+
diff --git a/articles/extensions/splunk.md b/articles/extensions/splunk.md
index ddf68bbc81..62facb383e 100644
--- a/articles/extensions/splunk.md
+++ b/articles/extensions/splunk.md
@@ -1,8 +1,14 @@
---
-description: How to configure and retrieve information using the Auth0 Logs to Splunk extension.
+description: Learn how to configure and retrieve information using the Auth0 Logs to Splunk extension.
+topics:
+ - extensions
+ - splunk
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
-# Auth0 Logs to Splunk
+# Export Logs to Splunk Using the Auth0 Extension
The _Auth0 Logs to Splunk_ is a scheduled job that takes all of your Auth0 logs and exports them to [Splunk](http://www.splunk.com/).
@@ -15,16 +21,19 @@ To install and configure this extension, click on the _Auth0 Logs to Splunk_ box
At this point you should set the following configuration variables:
- **Schedule**: How often the job will run. The schedule can be customized even further after creation.
+- **START_FROM**: The checkpoint ID of the log from where you want to start. The value will be the log id (GUID).
- **SPLUNK_URL**: Your Splunk Cloud URL.
- **SPLUNK_TOKEN**: Your Splunk Token.
- **SPLUNK_COLLECTOR_PORT**: The Port of your HTTP Collector Endpoint.
- **SPLUNK_COLLECTOR_PATH**: The [HTTP Collector Endpoint](http://dev.splunk.com/view/event-collector/SP-CAAAE7H) to be used. If you use the `/raw` endpoint, make sure to append a channel as a querystring parameter, like this: `/services/collector/raw?channel=FE0ECFAD-13D5-401B-847D-77833BD77131`. More information can be found in the [Splunk documentation](http://dev.splunk.com/view/event-collector/SP-CAAAE8Y).
-- **BATCH_SIZE**: The ammount of logs to be read on each execution. Maximun is 100.
+- **BATCH_SIZE**: The amount of logs to be read on each execution. Maximum is 100.
- **LOG_LEVEL**: The minimal log level of events that you would like sent to Splunk.
- **LOG_TYPES**: The events for which logs should be exported.
Once you have provided this information, click the *Install* button to finish installing the extension.
+<%= include('./_includes/_batch-size') %>
+
## Retrieve the required information from Splunk
The HTTP Event Collector (HEC) is an endpoint that lets you send application events into Splunk Enterprise using the HTTP or Secure HTTP (HTTPS) protocols. In order to configure a new HTTP Event Collector for Auth0 logs and acquire the URL, Token and Port information, follow the next steps:
@@ -65,7 +74,7 @@ curl -k https://:8088/services/collector -H 'Authorization: Splunk
The `` value is based on your _Splunk Cloud URL_. When creating requests to Splunk Cloud, you must add a prefix to the URI of the hostname according to your subscription. For self-service Splunk Cloud plans, pre-pend the hostname with `input-`. For all other Splunk Cloud plans, pre-pend the hostname with `http-inputs-`. For this example we have subscribed for a self-service Splunk Cloud plan, so we will use the `input-` prefix. You can find more details [here](http://dev.splunk.com/view/event-collector/SP-CAAAE7F).
:::
-As a response you should receive the followins JSON:
+As a response you should receive the following JSON:
```json
{
diff --git a/articles/extensions/sso-dashboard.md b/articles/extensions/sso-dashboard.md
index 3e61af5cdc..3d732fd70d 100644
--- a/articles/extensions/sso-dashboard.md
+++ b/articles/extensions/sso-dashboard.md
@@ -1,135 +1,45 @@
---
-title: "Auth0 Extension: Single Sign-On (SSO) Dashboard"
-description: This page explains how to configure and utilize the SSO Dashboard Extension.
-toc: true
+description: Understand how the SSO Dashboard Extension enables you to manage SSO login for your users on multiple enterprise applications.
+classes: topic-page
+topics:
+ - extensions
+ - sso-dashboard
+ - sso
+contentType:
+ - concept
+useCase:
+ - extensibility-extensions
+ - setup-multiple-applications
+ - setup-sso-dashboard
---
-# Auth0 Extension: Single Sign-On (SSO) Dashboard
+# Auth0 Single Sign-On Dashboard Extension
-The **SSO Dashboard** extension allows you to create a dashboard with multiple enterprise applications that can be enabled for single sign-on for your users for login.
+The **Single Sign-on (SSO) Dashboard** is a web application designed to solve a problem familiar to many people. Organizations of all sizes maintain a variety of different applications to handle various business functions like accounting, HR, development, support, etc. Remembering usernames and passwords and login URLs for all of your applications can be cumbersome. With this extension, you can simplify the authentication experience by enabling SSO login for your users on multiple enterprise applications. It allows you to create a list of all the cloud services for which a user can authenticate with SSO logins.
-The SSO dashboard supports two types of users:
-**Users**- who will login to the dashboard to then select an application to sign into with SSO.
-**Admins**- can login to configure the applications that are visible to the users. This guide is intended for Dashboard Admins.
+::: note
+A user should not be able to access, from the dashboard or otherwise, the service provider without having appropriate permissions (groups/roles) to do so. Ideally, these users would not see any service provider they are not granted access to on the dashboard.
+:::
-[View this Extension on GitHub](https://github.com/auth0-extensions/auth0-sso-dashboard-extension)
+The SSO Dashboard supports two types of users:
+- **Users** who can login to the dashboard to select an application to sign into with SSO.
+- **Admins** who can configure applications visible to the users.
-## Create an application
+To setup and configure this extension, do the following steps:
-Let's start with creating a new application. Navigate to [Applications](${manage_url}/#/applications) and click on the **+Create Application** button. Set a name and choose **Single Page Web Applications** application type. Click on **Create**.
-
-
-
-Click on the *Settings* tab and set the **Allowed Callback URLs**. This varies based on your location.
-
-The login URL for **Admins**:
-
-| Location | Allowed Callback URL |
-| --- | --- |
-| USA | `https://${account.tenant}.us.webtask.io/auth0-sso-dashboard/admins/login` |
-| Europe | `https://${account.tenant}.eu.webtask.io/auth0-sso-dashboard/admins/login` |
-| Australia | `https://${account.tenant}.au.webtask.io/auth0-sso-dashboard/admins/login` |
-
-The login URL for **Users**:
-
-| Location | Allowed Callback URL |
-| --- | --- |
-| USA | `https://${account.tenant}.us.webtask.io/auth0-sso-dashboard/login` |
-| Europe | `https://${account.tenant}.eu.webtask.io/auth0-sso-dashboard/login` |
-| Australia | `https://${account.tenant}.au.webtask.io/auth0-sso-dashboard/login` |
-
-Copy the **Client ID** value.
-
-Navigate to *Settings > Show Advanced Settings > OAuth* and paste the **Client ID** value to the **Allowed APPs / APIs** field.
-
-Set the **JsonWebToken Signature Algorithm** to *RS256*.
-
-
-
-Save your changes.
-
-### Application connections
-
-By default all the connection types are enabled for users to be able to login into the SSO Dashbboard. If you would like to change this, navigate to the *Connections* tab for the Application.
-
-## Install the extension
-
-We are now ready to setup our new extension. But first, head back to your newly created Application and copy the **Client ID** value.
-
-To install and configure this extension, click on the **SSO Dashboard** box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the dashboard. The **Install Extension** window will open.
-
-
-
-Set the following configuration variables:
-
-- **EXTENSION_CLIENT_ID**: This is the **Client ID** of the application you have created in the [Applications](${manage_url}/#/applications) that you wish to use this extension with.
-- **TITLE**: This the custom title that will appear at the top of the SSO Dashboard page.
-- **CUSTOM_CSS** *Optional*: This field that can contain a link to custom CSS you can use to style the look of your SSO Dashboard page.
-
-Once you have provided this information, click **INSTALL**.
-
-If you navigate back to the [Applications](${manage_url}/#/applications) view, you will see that there has been an additional application created.
-
-
-
-The `auth0-sso-dashboard` application is created automatically when you install the extension. It's an application authorized to access the [Management API](/api/management/v2) and you shouldn't modify it.
-
-## Use the extension
-
-Navigate to the [Extensions](${manage_url}/#/extensions) page and click on the **Installed Extensions** tab.
-
-Click on the row for the **SSO Dashboard** extension. The first time you click on your installed extension, you will be asked to grant it the required permissions.
-
-Once you agree, you will be directed to your custom **SSO Dashboard** page, which will have the **TITLE** you provided at the top of the page, and if you provided a custom CSS file that styling will be applied.
-
-
-
-To login into the dashboard:
-
-For **Admins** use `https://${account.tenant}..webtask.io/auth0-sso-dashboard/admins/login` or through the Dashboard.
-
-For **Users** use `https://${account.tenant}..webtask.io/auth0-sso-dashboard/login`.
-
-### Add a new application
-
-To add a new application to your dashboard to be used for single sign-on, go to the **Settings** page of the dashboard by clicking on the link on the upper right corner of the page and click **Settings** from the dropdown.
-
-Then click on the **CREATE APP** button to add a new application.
-
-
-
-You will then need to enter the following fields for the new application:
-
-* **Type**: This field is a dropdown where you select the either SAML, OpenID-Connect, or WS-Federation depending on the type of application.
-* **Application**: This is the application name of the application you have created that you wish to associate the login of users.
-* **Name**: The name of the new application you are adding.
-* **Logo**: Enter the url of the logo you wish to user as an icon for the application.
-* **Callback**: This is one of the **Allowed Callback URLs** under your [Application Settings](${manage_url}/#/applications) of the application.
-* **Connection** *Optional*: Select the connection type from the dropdown. You can add/edit your available connection types in the [Connections section of the Auth0 Management dashboard](${manage_url}/#/connections/database). If a connection is not set and the user is not logged, the user will see the Auth0 Login page.
-* **Enabled**: Select this checkbox for this application to be visible (published) to your users.
-
-
-
-Once completed click the **CREATE** button.
-
-Your new application will then appear on the **Applications** page of the SSO dashboard with any other applications that have been created.
-
-
-
-You can click on an application here to test the connection.
-
-### Update an existing application
-
-To edit an existing application go to the **Settings** page of the dashboard by clicking on the link on the upper right corner of the page and click **Settings** from the dropdown.
-
-You can change whether users can see the application (if it is enabled) with the **Publish** or **Unpublish** buttons.
-
-You can delete an application with the **X** button, a confirmation box will popup to confirm the deletion.
-
-To update an application's settings, click the gear icon.
-
-
-
-Here you can change any of your application settings, or delete an application.
+<%= include('../_includes/_topic-links', { links: [
+ 'dashboard/guides/extensions/sso-dashboard-create-app',
+ 'dashboard/guides/extensions/sso-dashboard-install-extension',
+ 'dashboard/guides/extensions/sso-dashboard-add-apps',
+ 'dashboard/guides/extensions/sso-dashboard-update-apps',
+] }) %>
+## Keep reading
+- [View this Extension on GitHub](https://github.com/auth0-extensions/auth0-sso-dashboard-extension)
+- [Troubleshoot Extensions](/extensions/troubleshoot)
+- [Understand how Single Sign-On works with Auth0](/sso/current/sso-auth0)
+- Learn how to [enable SSO in Auth0](/dashboard/guides/tenants/enable-sso-tenant)
+- [Understand session lifetime](/sessions/concepts/session-lifetime)
+- Learn how to [configure session lifetime settings](/dashboard/guides/tenants/configure-session-lifetime-settings)
+- Learn how to [log users out](/logout)
diff --git a/articles/extensions/sumologic.md b/articles/extensions/sumologic.md
index 7d2037cf3d..5e6a1cef8e 100644
--- a/articles/extensions/sumologic.md
+++ b/articles/extensions/sumologic.md
@@ -1,75 +1,99 @@
---
description: How to configure and retrieve information using the Auth0 Logs to Sumo Logic extension.
+topics:
+ - extensions
+ - sumologic
+contentType:
+ - how-to
+useCase: extensibility-extensions
+toc: true
---
# Auth0 Logs to Sumo Logic
-The _Auth0 Logs to Sumo Logic_ is a scheduled job that takes all of your Auth0 logs and exports them to [Sumo Logic](https://www.sumologic.com/).
+The Auth0 Logs to Sumo Logic is a scheduled job that takes all of your Auth0 logs and exports them to [Sumo Logic](https://www.sumologic.com/). This document will guide you through the process of setting up this integration.
-## Configuring the Extension
+## Step 1: Create a Sumo Logic HTTP endpoint
-To install and configure this extension, click on the _Auth0 Logs to Sumo Logic_ box in the list of provided extensions on the [Extensions](${manage_url}/#/extensions) page of the [Management Portal](${manage_url}). The _Install Extension_ window pops open.
+1. Login to [Sumo Logic](https://www.sumologic.com/) and from the top menu select **Manage > Setup Wizard**.
-
+
-At this point you should set the following configuration variables:
+2. On the next screen click **Set Up Streaming Data**.
-- **Schedule**: The frequency with which logs should be exported. The schedule can be customized even further after creation.
-- **BATCH_SIZE**: The ammount of logs to be read on each execution. Maximun is 100.
-- **SUMOLOGIC_URL**: Your Sumo Logic HTTP Collector Endpoint.
-- **LOG_LEVEL**: The minimal log level of events that you would like sent to Sumo Logic.
-- **LOG_TYPES**: The events for which logs should be exported.
+3. At the **Select Data Type** page, select **Your Custom App**.
+
+
+
+4. Select **HTTP Source** as the way to collect the logs.
+
+
+
+5. Modify the **Source Category** and select a time zone for your log file. Click **Continue**.
-Once you have provided this information, click the *Install* button to finish installing the extension.
+6. You should now be provided with a URL. This is the **HTTP Source** that Sumo Logic configured for you. Copy the value and click **Continue**. Exit the setup wizard.
-## Retrieve the required information from Sumo Logic
+
-In order to configure a new system for Auth0 logs and acquire the *SUMOLOGIC_URL* information, follow the next steps:
-1. Login to [Sumo Logic](https://www.sumologic.com/) and from the top menu select _Manage > Setup Wizard_.
+7. Now head back to the Auth0 Dashboard to set the value you copied as the value for **SUMOLOGIC_URL**.
-
+## Step 2: Configure the Extension
-2. On the next screen click _Set Up Streaming Data_.
-3. At the _Select Data Type_ page, select _Your Custom App_.
+To install and configure this extension, go to [Dashboard > Extensions](${manage_url}/#/extensions) and click on the **Auth0 Logs to Sumo Logic** box.
-
+The **Install Extension** window pops open.
+
+
+
+At this point you should set the following configuration parameters:
+
+- **Schedule**: The frequency with which logs should be exported. The schedule can be customized even further after creation.
+- **BATCH_SIZE**: Logs are batched before sending. Multiple batches are sent each time the extension runs. Specify the number of logs per batch. Maximum is `100`.
+- **SUMOLOGIC_URL**: Your Sumo Logic HTTP Collector Endpoint. Set the value you copied at the previous step.
+- **LOG_LEVEL**: The minimal log level of events that you would like sent to Sumo Logic.
+- **LOG_TYPES**: The events for which logs should be exported.
+- **START_FROM**: The `log_id` of the log you would like to start sending from. Default is to start with the oldest available log.
+- **SLACK_INCOMING_WEBHOOK_URL**: Send reports from the extension to the specific Slack webhook.
+- **SLACK_SEND_SUCCESS**: Send even more stuff to Slack. Useful for troubleshooting.
-4. Select _HTTP Source_ as the way to collect the logs.
+Once you have provided this information, click the **Install** button to finish installing the extension.
-
+The integration between Auth0 and Sumo Logic is now in place!
-5. Modify the _Source Category_ and select a time zone for your log file. Click Continue.
-6. You should now be provided with a URL. This is the _HTTP Source_ that Sumo Logic configured for you. Copy the value and click _Continue_. Exit the setup wizard.
+<%= include('./_includes/_batch-size') %>
-
+## How to view the results
-7. Now head back to the Auth0 Dashboard and set the value you copied as the value for **SUMOLOGIC_URL**.
+The integration you just setup, created a scheduled job that will be responsible to export the logs.
-## Using Your Installed Extension
+To view this scheduled job:
+- Go to [Dashboard > Extensions](${manage_url}/#/extensions)
+- Click on the **Installed Extensions** link
+- Select the **Auth0 Logs to Sumo Logic** line.
- To view all scheduled jobs, navigate to the [Extensions](${manage_url}/#/extensions) page of the [Management Portal](${manage_url}), click on the *Installed Extensions* link, and select the *Auth0 Logs to Sumo Logic* line. There you can see the job you just created, modify its state by toggling the *State* switch, see when the next run is due and what was the result of the last execution.
+There you can see the job you just created, modify its state by toggling the **State** switch, see when the next run is due and what was the result of the last execution.
-
+
You can view more details by clicking on the job you created. In this page you can view details for each execution, reschedule, access realtime logs, and more.
-
+
That's it, you are done! You can now navigate to [Sumo Logic](https://www.sumologic.com/) and view your [Auth0 Logs](${manage_url}/#/logs), by selecting the configured system.
-
+
-## Auth0 Dashboard
+## Use the Auth0 Dashboard
Here, at Auth0, we have been using the Auth0 to Sumo Logic extension ourselves since it was first released, and it's proven to be very useful for staying on top of what's happening with our own Auth0 accounts and our internal users. Sumo Logic makes it easy to see the latest failed logins, find and alert on error messages, create charts to visualize trends, or even do complex statistical analysis on your data.
To help us (and our customers) visualize these logs, we spent some time creating a dashboard. The Sumo Logic for Auth0 dashboard shows you the output of several saved searches all on one easy to read screen, and makes it easy to zoom in or drill down when something looks interesting.
-
+
If you're a Sumo Logic customer and are interested in trying out this dashboard, you can find details on installing the Auth0 App for the Sumo Logic extension here:
-[Install the Auth0 App](https://help.sumologic.com/Send_Data/Data_Types/Auth0/02Install_the_Auth0_App)
+[Install the Auth0 App](https://help.sumologic.com/07Sumo-Logic-Apps/20SAML/Auth0/Auth0-App-Dashboards)
Once it's available through your account, you're free to customize it, add to it, create alerts based on the searches, or really anything else that you find useful.
diff --git a/articles/extensions/troubleshoot.md b/articles/extensions/troubleshoot.md
new file mode 100644
index 0000000000..a42a424117
--- /dev/null
+++ b/articles/extensions/troubleshoot.md
@@ -0,0 +1,38 @@
+---
+description: General troubleshooting steps for extensions.
+topics:
+ - extensions
+ - troubleshooting
+ - errors
+contentType:
+ - how-to
+useCase:
+ - extensibility-extensions
+ - troubleshooting
+---
+# Troubleshoot Extensions
+
+If you see issues with your [extensions](/extensions), we recommend that you begin the troubleshooting process with the following two steps:
+
+1. Reinstall the extension.
+2. Migrate to Node.js v12.
+
+## Reinstall the Extension
+
+One of the first things you can do when running into issues with an extension is to reinstall it:
+
+1. Go to [Dashboard > Extensions](${manage_url}/#/extensions).
+2. On the **Installed Extensions** tab, delete the extension.
+3. Log out of the Auth0 Dashboard.
+4. Log back in to the Auth0 Dashboard.
+5. Reinstall and reconfigure the extension.
+
+## Migrate to Node.js v12
+
+We recommend changing your tenant's extensibility runtime from Node.js v8 to Node.js v12. Before updating, however, review the [migration guide](/migrations/guides/extensibility-node12) for full details on what will be affected by this change.
+
+You can change the Node.js runtime version by going to the **Extensibility** section in [Tenant Settings > Advanced](https://manage.auth0.com/#/tenant/advanced).
+
+## Contact Support
+
+If you are still experiencing issues with your extensions, and you need to [contact support](https://support.auth0.com/), please be sure to **include errors logs and/or [real-time Webtask logs](/extensions/realtime-webtask-logs) with your support ticket**. Errors and logs can help Auth0 support troubleshoot your issue faster.
diff --git a/articles/extensions/user-import-export.md b/articles/extensions/user-import-export.md
index 1b7bed87e5..45528fde69 100644
--- a/articles/extensions/user-import-export.md
+++ b/articles/extensions/user-import-export.md
@@ -2,18 +2,22 @@
title: User Import / Export Extension
toc: true
description: The User Import / Export is an extension that allows you to import / export users from or to any database you have configured in your account.
+topics:
+ - extensions
+ - user-import-export
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# User Import / Export
-::: note
-The User Import / Export extension is available in the PSaaS Appliance beginning with version `10755` when you have user search enabled.
-:::
-
The **User Import / Export Extension** allows you to:
* Bulk import your existing database users into Auth0
* Search for and export some (or all) of your Auth0 database users
+For a list of user profile fields that can be imported and exported, see [User Profile Attributes](/users/references/user-profile-structure#user-profile-attributes).
+
You must be a Dashboard Admin to use this extension.
## Install the Extension
@@ -65,20 +69,20 @@ Once you've imported your users, you can manage them individually using the [Use
### Export Users
+::: note
+Auth0 uses the [ndjson](http://ndjson.org/) format due to the large size of export files. Before you can import users, you'll need to convert from **ndjson** to **json** using the library of your choice (such as [jq](https://stedolan.github.io/jq/)). When exporting users intended to later be imported, user field names should be left as their defaults and not mapped to a Column Name.
+:::
+
To export your existing Auth0 users associated with database connections, select **Export** in the left-hand navigation bar.

-You can query the users that you want to export using [Lucene query syntax](http://www.lucenetutorial.com/lucene-query-syntax.html) in the search bar. For example, to return all the users that have the `nickname` attribute you can use: `_exists_:nickname`.
+Under **User Fields**, you can decide which user attributes or expressions should be included in the export. The user attribute can be a static value like `user.user_metadata.name`, or it can be a JavaScript expression like `user.user_metadata.name || user.name`. Expressions will be evaluated during the export runtime. The **column name** value is how the value will be represented in the export.
-Under **Columns**, you can decide which user attributes or expressions should be included in the export. The user attribute can be a static value like `user.user_metadata.name`, or it can be a JavaScript expression like `user.user_metadata.name || user.name`. Expressions will be evaluated during the export runtime. The **column name** value is how the value will be represented in the export.
-
-You can use the **Add Default Columns** button to automatically select the default attributes and populate their column names (this is also a good way for you to visualize how parameters/expressions will appear).
+You can click the **Add Default Fields** button to automatically select the default fields and populate their column names (this is also a good way for you to visualize how parameters/expressions will appear).
You can remove extraneous attributes/expressions by clicking on its associated **trash can** icon.
-
-
Under **Settings**, you can:
* Configure how your exported users are listed by providing a **User Attribute** by which users should be sorted (as well as whether the users should be sorted in ascending or descending order)
diff --git a/articles/extensions/using-provided-extensions.md b/articles/extensions/using-provided-extensions.md
index e15cadd277..6581cc99ab 100644
--- a/articles/extensions/using-provided-extensions.md
+++ b/articles/extensions/using-provided-extensions.md
@@ -1,5 +1,10 @@
---
description: Links and information on using Auth0's provided extensions.
+topics:
+ - extensions
+contentType:
+ - index
+useCase: extensibility-extensions
---
# Using Auth0's Provided Extensions
diff --git a/articles/extensions/visual-studio-team-services-deploy.md b/articles/extensions/visual-studio-team-services-deploy.md
index 7ebc668765..3c62c18309 100644
--- a/articles/extensions/visual-studio-team-services-deploy.md
+++ b/articles/extensions/visual-studio-team-services-deploy.md
@@ -1,10 +1,16 @@
---
-description: The Visual Studio Team Services Deployments extension allows you to deploy Rules, Hosted Pages and Database Connection scripts from Visual Studio Team Services to Auth0.
+description: The Visual Studio Team Services Deployments extension allows you to deploy Rules, Universal Login pages and database connection scripts from Visual Studio Team Services to Auth0.
+topics:
+ - extensions
+ - vs-team-services-deployments
+contentType:
+ - how-to
+useCase: extensibility-extensions
---
# Visual Studio Team Services Deployments
-The **Visual Studio Team Services Deployments** extension allows you to deploy [Rules](/rules), Database Connection scripts and hosted pages from Visual Studio Team Services to Auth0. You can configure a Visual Studio Team Services project, keep all of your scripts there, and have them automatically deployed to Auth0 whenever you push changes to your project.
+The **Visual Studio Team Services Deployments** extension allows you to deploy [rules](/rules), rules configs, connections, database connection scripts, clients, client grants, resource servers, Universal Login pages and email templates from Visual Studio Team Services to Auth0. You can configure a Visual Studio Team Services project, keep all of your scripts there, and have them automatically deployed to Auth0 whenever you push changes to your project.
## Configure the Auth0 Extension
@@ -14,15 +20,21 @@ To install and configure this extension, click on the **Visual Studio Team Servi
Set the following configuration variables:
-* **TFS_TYPE**: The type of repository, choose from TFVC or Git
-* **TFS_PROJECT**: The project from which you want to deploy rules and database scripts.
-* **TFS_BRANCH**: The branch we should monitor for commits.
-* **TFS_INSTANCE**: Your Visual Studio Team Services instance name (without .visualstudio.com).
-* **TFS_COLLECTION**: Your visualstudio collection
-* **TFS_USERNAME**: Your Visual Studio Team Services username
-* **TFS_TOKEN**: Your personal Access Token for Visual Studio Team Services, for details on how to configure one refer to [Configure a Personal Access Token](#configure-a-personal-access-token) below.
+* **TYPE**: The type of repository, choose from TFVC or Git
+* **REPOSITORY**: The project from which you want to deploy rules and database scripts. To use a specific repository within a project, format your input value as follows: `projectName/repoName`.
+* **BRANCH**: The branch we should monitor for commits.
+* **INSTANCE**: Your Visual Studio Team Services instance name (without .visualstudio.com).
+* **COLLECTION**: Your Visual Studio collection (DefaultCollection for Azure DevOps).
+* **USERNAME**: Your Visual Studio Team Services username
+* **TOKEN**: Your personal Access Token for Visual Studio Team Services, for details on how to configure one refer to [Configure a Personal Access Token](#configure-a-personal-access-token) below.
+* **BASE_DIR**: The base directory, where all your tenant settings are stored
+* **AUTO_REDEPLOY**: If enabled, the extension redeploys the last successful configuration in the event of a deployment failure. Manual deployments and validation errors does not trigger auto-redeployment
* **SLACK_INCOMING_WEBHOOK**: Webhook URL for Slack used to notify you of successful and failed deployments.
+::: note
+Some of the configuration variables were changed in version **2.5.0** of this extension. If you are updating the extension from a prior version, make sure that you update your configuration accordingly.
+:::
+
Once you have provided this information, click **Install**.
## Configure a Personal Access Token
@@ -41,7 +53,7 @@ Once you have provided this information, click **Install**.

-5. Once the token is created, you will need to copy right away as it is not saved. Use this value as your **TFS_TOKEN**.
+5. Once the token is created, you will need to save its value manually right away. Use this value as your **TFS_TOKEN**.

@@ -59,11 +71,11 @@ Once you agree, you will be directed to the **Visual Studio Team Services Integr

-Copy the **Payload URL** and **HTTP headers** values. You will use them in order to configure the Visual Studio Team Services Webhook in the next step.
+Copy the **Payload URL** and **HTTP headers** values. You will use them to configure the Visual Studio Team Services Webhook in the next step.
## Configure the Visual Studio Team Services Webhook
-Once you have configured your Auth0 Extension, you will need to configure the the Visual Studio Team Services Webhook to complete the integration.
+Once you have configured your Auth0 Extension, you will need to configure the Visual Studio Team Services Webhook to complete the integration.
In your Visual Studio Team Services account, go to **Overview** and click on the name the project being used for the integration, then click **Service Hooks**.
@@ -73,7 +85,7 @@ Then click the link **Create the first subscription for this project**. Then sel

-Then click the **Next** button, choose the trigger for the event and the filters are optional. Then click **Next**.
+Then click the **Next** button, choose the trigger for the event, and the filters are optional. Then click **Next**.

@@ -83,14 +95,18 @@ For the **URL** field, enter the **Payload URL** from the previous step along wi
Once you have set up the webhook in Visual Studio Team Services using the provided information, you are ready to start committing to your project.
-Your project should have a predefined structure:
-- Rules are expected to be found under `rules` directory.
-- Database connections are expected to be found under `database-connections` directory.
-- Hosted pages are expected to be found under `pages` directory.
+With each commit you push to your configured Visual Studio Team Services project, the webhook will call the extension to initiate a deployment if changes were made to one of these folders:
+- `clients`
+- `grants`
+- `emails`
+- `resource-servers`
+- `connections`
+- `database-connections`
+- `rules-configs`
+- `rules`
+- `pages`
-With each commit you push to your configured Visual Studio Team Services project, the webhook will call the extension to initiate a deployment if changes were made to these predefined directories.
-
-The **Deploy** button on the **Deployments** tab of the extension allows you to manually deploy the Rules, Pages and Database Connection scripts that you already have in your Visual Studio Team Services project. This is useful if your project already contains items that you want to deploy once you have set up the extension or if you have accidentally deleted some scripts in Auth0 and need to redeploy the latest version of your project.
+The **Deploy** button on the **Deployments** tab of the extension allows you to manually deploy the Rules, Pages, and Database Connection scripts that you already have in your Visual Studio Team Services project. This is useful if your project already contains items that you want to deploy once you have set up the extension or if you have accidentally deleted some scripts in Auth0 and need to redeploy the latest version of your project.
::: panel-warning Full Deployment
To maintain a consistent state, the extension will always do a full deployment of the contents of these folders. **Any rules, pages or database connection scripts that exist in Auth0 but not in your Visual Studio Team Services project will be deleted**.
@@ -113,31 +129,67 @@ For a generic Custom Database Connection, only the `login.js` script is required
You can find examples in [the Auth0 Samples repository](https://github.com/auth0-samples/github-source-control-integration/tree/master/database-connections/my-custom-db). While the samples were authored for GitHub, it will work for a Visual Studio Team Services integration as well.
-### Deploy Hosted Pages
+#### Deploy Database Connection Settings
+
+To deploy Database Connection settings, you must create `database-connections/[connection-name]/database.json`.
+
+_This will work only for Auth0 connections (`strategy === auth0`), for non-Auth0 connections, use `connections`._
+
+_Support for using `settings.json` has been deprecated in favor of `database.json` since v3.1.1 of the extension and may be dropped in a future release._
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Connections/patch_connections_by_id) for more info on allowed attributes for Connections.
+
+### Deploy Connections
+
+To deploy a connection, you must create a JSON file under the `connections` directory of your Visual Studio Team Services project. Example:
+
+__facebook.json__
+```json
+{
+ "name": "facebook",
+ "strategy": "facebook",
+ "enabled_clients": [
+ "my-client"
+ ],
+ "options": {}
+}
+```
+
+<%= include('./_includes/_embedded-clients-array') %>
+
+_This will work only for non-Auth0 connections (`strategy !== auth0`), for Auth0 connections, use `database-connections`._
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Connections/post_connections) for more info on allowed attributes for Connections.
+
+### Deploy Universal Login Pages
+
+The supported pages are:
-The supported hosted pages are:
- `error_page`
- `guardian_multifactor`
- `login`
- `password_reset`
-To deploy a page, you must create an HTML file under the `pages` directory of your Visual Studio Team Services project. For each HTML page you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, in order to deploy an `error_page`, you would create two files:
+To deploy a page, you must create an HTML file under the `pages` directory of your Visual Studio Team Services project. For each HTML page, you need to create a JSON file (with the same name) that will be used to mark the page as enabled or disabled. For example, to deploy a `password_reset`, you would create two files:
```text
-your-project/pages/error_page.html
-your-project/pages/error_page.json
+your-bitbucket-repo/pages/password_reset.html
+your-bitbucket-repo/pages/password_reset.json
```
-To enable the page the `error_page.json` would contain the following:
+To enable the page, the `password_reset.json` would contain the following:
```json
{
"enabled": true
}
```
+
+<%= include('./_includes/_use-default-error') %>
+
### Deploy Rules
-To deploy a rule, you must first create a JavaScript file under the `rules` directory of your Visual Studio Team Services project. Each Rule must be in its own `.js` file.
+To deploy a rule, you must first create a JavaScript file under the `rules` directory of your Visual Studio Team Services project. Each Rule must be in its own JavaScript file.
For example, if you create the file `rules/set-country.js`, the extension will create a Rule in Auth0 with the name `set-country`.
@@ -145,10 +197,6 @@ For example, if you create the file `rules/set-country.js`, the extension will c
If you plan to use source control integration for an existing account, first rename your Rules in Auth0 to match the name of the files you will be deploying to this directory.
:::
-You can mark rules as manual. In that case, the source control extension will not delete or update them. To mark a rule navigate to the **Rules Configuration** tab of the **Visual Studio Team Services Integration** page. Toggle the **Manual Rule** switch for the rules you want to mark as manual. Click **Update Manual Rules** to save your changes.
-
-
-
You can also control the Rule order and status (`enabled`/`disabled`) by creating a JSON file with the same name as your JavaScript file. For this example, you would create a file named `rules/set-country.json`.
__set-country.js__
@@ -162,7 +210,7 @@ function (user, context, callback) {
```
__set-country.json__
-```javascript
+```json
{
"enabled": false,
"order": 15,
@@ -174,16 +222,167 @@ You can find a `login_success` example in [the Auth0 Samples repository](https:/
#### Set Rule Order
-To avoid conflicts, you are cannot set multiple Rules of the same order. However, you can create a JSON file for each rule, and within each file, assign a value for `order`. We suggest using number values that allow for reordering with less risk for conflict. For example, assign a value of `10` to the first Rule and `20` to the second Rule, rather than using values of `1` and `2`, respectively).
+To avoid conflicts, you cannot set multiple Rules of the same order. However, you can create a JSON file for each rule, and within each file, assign a value for `order`. We suggest using number values that allow for reordering with less risk of conflict. For example, assign a value of `10` to the first Rule and `20` to the second Rule, rather than using values of `1` and `2`, respectively).
#### Set the Stage
-After you deploy a Rule, you cannot change its stage, or the area where the Rule executes.
+After you deploy a Rule, you cannot change its stage or the area where the Rule executes.
If you need the rule to execute in a different stage, you must create a new Rule with the updated stage and delete the original Rule.
Please note that you may have only a single Rule for the `user_registration` and `login_failure` stages.
+### Deploy Rules Configs
+
+To deploy a rule config, you must create a JSON file under the `rules-configs` directory of your Visual Studio Team Services project. Example:
+
+__secret_number.json__
+```json
+{
+ "key": "secret_number",
+ "value": 42
+}
+```
+
+### Deploy Clients
+
+To deploy a client, you must create a JSON file under the `clients` directory of your Visual Studio Team Services project. Example:
+
+__my-client.json__
+```json
+{
+ "name": "my-client"
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Clients/post_clients) for more info on allowed attributes for Clients and Client Grants.
+
+### Deploy Clients Grants
+
+You can specify the client grants for each client by creating a JSON file in the `grants` directory.
+
+__my-client-api.json__
+```json
+{
+ "client_id": "my-client",
+ "audience": "https://myapp.com/api/v1",
+ "scope": [
+ "read:users"
+ ]
+}
+```
+
+<%= include('./_includes/_deployment-extension') %>
+
+### Deploy Resource Servers
+
+To deploy a resource server, you must create a JSON file under the `resource-servers` directory of your Visual Studio Team Services project. Example:
+
+__my-api.json__
+```json
+{
+ "name": "my-api",
+ "identifier": "https://myapp.com/api/v1",
+ "scopes": [
+ {
+ "value": "read:users",
+ "description": "Allows getting user information"
+ }
+ ]
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Resource_Servers/post_resource_servers) for more info on allowed attributes for Resource Servers.
+
+### Deploy Email Provider
+
+To deploy an email provider, you must create `provider.json` file under the `emails` directory of your Visual Studio Team Services project. Example:
+
+__provider.json__
+```json
+{
+ "name": "smtp",
+ "enabled": true,
+ "credentials": {
+ "smtp_host": "smtp.server.com",
+ "smtp_port": 25,
+ "smtp_user": "smtp_user",
+ "smtp_pass": "smtp_secret_password"
+ }
+}
+```
+
+See [Management API v2 Docs](https://auth0.com/docs/api/management/v2#!/Emails/patch_provider) for more info on allowed attributes for Email Provider.
+
+### Deploy Email Templates
+
+The supported email templates are:
+- `verify_email`
+- `reset_email`
+- `welcome_email`
+- `blocked_account`
+- `stolen_credentials`
+- `enrollment_email`
+- `mfa_oob_code`
+
+To deploy an email template, you must create an HTML file under the `emails` directory of your Visual Studio Team Services project. For each HTML file, you need to create a JSON file (with the same name) with additional options for that template. For example, to deploy a `blocked_account` template, you would create two files:
+
+```text
+your-project/emails/blocked_account.html
+your-project/emails/blocked_account.json
+```
+
+__blocked_account.json__
+```json
+{
+ "template": "blocked_account",
+ "from": "",
+ "subject": "",
+ "resultUrl": "",
+ "syntax": "liquid",
+ "body": "./blocked_account.html",
+ "urlLifetimeInSeconds": 432000,
+ "enabled": true
+}
+```
+
+## Excluded records
+
+You can exclude the following records from the deployment process: `rules`, `clients`, `databases`, `connections` and `resourceServers`. If excluded, the records will not be modified by deployments.
+
+
+
+## Keywords Mapping
+
+Beginning with version **3.0.0**, you can use keywords mapping to manage your secrets and tenant-based environment variables.
+
+There are two ways to use the keyword mappings. You can either wrap the key using `@` symbols (e.g., `@@key@@`), or you can wrap the key using `#` symbols (e.g., `##key##`).
+
+ - If you use `@` symbols, your value will be converted from a JavaScript object or value to a JSON string.
+
+ - If you use `#` symbols, Auth0 will perform a literal replacement.
+
+This is useful for something like specifying different variables across your environments. For example, you could specify different JWT timeouts for your Development, QA/Testing, and Production environments.
+
+Refer to the snippets below for sample implementations:
+
+__Client.json__
+```json
+{
+ ...
+ "callbacks": [
+ "##ENVIRONMENT_URL##/auth/callback"
+ ],
+ "jwt_configuration": {
+ "lifetime_in_seconds": ##JWT_TIMEOUT##,
+ "secret_encoded": true
+ }
+ ...
+}
+```
+
+
+
## Track Deployments
To track your deployments, navigate to the [Extensions](${manage_url}/#/extensions) page, then **Installed Extensions** and click on the row for the **Visual Studio Team Services Deployments** extension, and select the **Deployments** tab. You will see a list of all deployments.
diff --git a/articles/flows/concepts/auth-code-pkce.md b/articles/flows/concepts/auth-code-pkce.md
new file mode 100644
index 0000000000..5b0677b14e
--- /dev/null
+++ b/articles/flows/concepts/auth-code-pkce.md
@@ -0,0 +1,79 @@
+---
+title: Authorization Code Flow with Proof Key for Code Exchange (PKCE)
+description: Learn how the Authorization Code flow with Proof Key for Code Exchange (PKCE) works and why you should use it for native and mobile apps.
+topics:
+ - authorization-code
+ - pkce
+ - api-authorization
+ - grants
+ - authentication
+ - native-apps
+ - mobile-apps
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
+ - add-login
+---
+# Authorization Code Flow with Proof Key for Code Exchange (PKCE)
+
+When public clients (e.g., native and single-page applications) request Access Tokens, some additional security concerns are posed that are not mitigated by the Authorization Code Flow alone. This is because:
+
+**Native apps**
+
+* Cannot securely store a Client Secret. Decompiling the app will reveal the Client Secret, which is bound to the app and is the same for all users and devices.
+* May make use of a custom URL scheme to capture redirects (e.g., MyApp://) potentially allowing malicious applications to receive an Authorization Code from your Authorization Server.
+
+**Single-page apps**
+
+* Cannot securely store a Client Secret because their entire source is available to the browser.
+
+To mitigate this, OAuth 2.0 provides a version of the Authorization Code Flow which makes use of a Proof Key for Code Exchange (PKCE) (defined in [OAuth 2.0 RFC 7636](https://tools.ietf.org/html/rfc7636)).
+
+The PKCE-enhanced Authorization Code Flow introduces a secret created by the calling application that can be verified by the authorization server; this secret is called the Code Verifier. Additionally, the calling app creates a transform value of the Code Verifier called the Code Challenge and sends this value over HTTPS to retrieve an Authorization Code. This way, a malicious attacker can only intercept the Authorization Code, and they cannot exchange it for a token without the Code Verifier.
+
+## How it works
+
+Because the PKCE-enhanced Authorization Code Flow builds upon the [standard Authorization Code Flow](/flows/concepts/auth-code), the steps are very similar.
+
+
+
+1. The user clicks **Login** within the application.
+2. Auth0's SDK creates a cryptographically-random `code_verifier` and from this generates a `code_challenge`.
+3. Auth0's SDK redirects the user to the Auth0 Authorization Server ([**/authorize** endpoint](/api/authentication#authorization-code-grant-pkce-)) along with the `code_challenge`.
+4. Your Auth0 Authorization Server redirects the user to the login and authorization prompt.
+5. The user authenticates using one of the configured login options and may see a consent page listing the permissions Auth0 will give to the application.
+6. Your Auth0 Authorization Server stores the `code_challenge` and redirects the user back to the application with an authorization `code`, which is good for one use.
+7. Auth0's SDK sends this `code` and the `code_verifier` (created in step 2) to the Auth0 Authorization Server ([**/oauth/token** endpoint](/api/authentication?http#authorization-code-flow-with-pkce44)).
+8. Your Auth0 Authorization Server verifies the `code_challenge` and `code_verifier`.
+9. Your Auth0 Authorization Server responds with an ID Token and Access Token (and optionally, a Refresh Token).
+10. Your application can use the Access Token to call an API to access information about the user.
+11. The API responds with requested data.
+
+<%= include('../../_includes/_refresh_token_rotation_panel.md') %>
+
+## How to implement it
+
+The easiest way to implement the Authorization Code Flow with PKCE is to follow our [Native Quickstarts](/quickstart/native) or [Single-Page Quickstarts](/quickstart/spa).
+
+Depending on your application type, you can also use our mobile or single-page app SDKs:
+
+**Mobile**
+
+* [Auth0 Swift SDK](/libraries/auth0-swift)
+* [Auth0 Android SDK](/libraries/auth0-android)
+
+**Single-page**
+
+* [Auth0 Single-Page App SDK](/libraries/auth0-spa-js)
+* [Auth0 React SDK](/libraries/auth0-react)
+
+<%= include('../../_includes/_refresh_token_rotation_recommended.md') %>
+
+You can follow our tutorials to use our API endpoints to [Add Login Using the Authorization Code Flow with PKCE](/flows/guides/auth-code-pkce/add-login-auth-code-pkce) or [Call Your API Using the Authorization Code Flow with PKCE](/flows/guides/auth-code-pkce/call-api-auth-code-pkce).
+
+## Keep reading
+
+- Learn how to personalize your user's login experience using [rules](/rules) and [hooks](/hooks)
+- Learn more about [tokens](/tokens) and [token storage](/tokens/concepts/token-storage)
+- Explore [Which OAuth 2.0 Flow Should I Use?](/api-auth/which-oauth-flow-to-use)
diff --git a/articles/flows/concepts/auth-code.md b/articles/flows/concepts/auth-code.md
new file mode 100644
index 0000000000..a01f39b566
--- /dev/null
+++ b/articles/flows/concepts/auth-code.md
@@ -0,0 +1,46 @@
+---
+title: Authorization Code Flow
+description: Learn how the Authorization Code flow works and why you should use it for regular web apps.
+topics:
+ - authorization-code
+ - api-authorization
+ - grants
+ - authentication
+ - regular-web-apps
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
+ - add-login
+---
+# Authorization Code Flow
+
+Because regular web apps are server-side apps where the source code is not publicly exposed, they can use the Authorization Code Flow (defined in [OAuth 2.0 RFC 6749, section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)), which exchanges an Authorization Code for a token. Your app must be server-side because during this exchange, you must also pass along your application's Client Secret, which must always be kept secure, and you will have to store it in your client.
+
+## How it works
+
+
+
+
+1. The user clicks **Login** within the regular web application.
+2. Auth0's SDK redirects the user to the Auth0 Authorization Server ([**/authorize** endpoint](/api/authentication#authorization-code-grant)).
+3. Your Auth0 Authorization Server redirects the user to the login and authorization prompt.
+4. The user authenticates using one of the configured login options and may see a consent page listing the permissions Auth0 will give to the regular web application.
+5. Your Auth0 Authorization Server redirects the user back to the application with an authorization `code`, which is good for one use.
+6. Auth0's SDK sends this `code` to the Auth0 Authorization Server ([**/oauth/token** endpoint](/api/authentication?http#authorization-code-flow43)) along with the application's Client ID and Client Secret.
+7. Your Auth0 Authorization Server verifies the code, Client ID, and Client Secret.
+8. Your Auth0 Authorization Server responds with an ID Token and Access Token (and optionally, a Refresh Token).
+9. Your application can use the Access Token to call an API to access information about the user.
+10. The API responds with requested data.
+
+## How to implement it
+
+The easiest way to implement the Authorization Code Flow is to follow our [Regular Web App Quickstarts](/quickstart/webapp).
+
+Finally, you can follow our tutorials to use our API endpoints to [Add Login Using the Authorization Code Flow](/flows/guides/auth-code/add-login-auth-code) or [Call Your API Using the Authorization Code Flow](/flows/guides/auth-code/call-api-auth-code).
+
+## Keep reading
+
+- Learn how to personalize your user's login experience using [rules](/rules) and [hooks](/hooks)
+- Learn more about [tokens](/tokens) and [token storage](/tokens/concepts/token-storage)
+- Explore [Which OAuth 2.0 Flow Should I Use?](/api-auth/which-oauth-flow-to-use)
\ No newline at end of file
diff --git a/articles/flows/concepts/client-credentials.md b/articles/flows/concepts/client-credentials.md
new file mode 100644
index 0000000000..eebe4ee5c4
--- /dev/null
+++ b/articles/flows/concepts/client-credentials.md
@@ -0,0 +1,42 @@
+---
+title: Client Credentials Flow
+description: Learn how the Client Credentials flow works and why you should use it for machine-to-machine (M2M) apps.
+topics:
+ - M2M
+ - client-credentials
+ - api-authorization
+ - grants
+ - authentication
+ - m2m-apps
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
+---
+# Client Credentials Flow
+
+With machine-to-machine (M2M) applications, such as CLIs, daemons, or services running on your back-end, the system authenticates and authorizes the app rather than a user. For this scenario, typical authentication schemes like username + password or social logins don't make sense. Instead, M2M apps use the Client Credentials Flow (defined in [OAuth 2.0 RFC 6749, section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)), in which they pass along their Client ID and Client Secret to authenticate themselves and get a token.
+
+## How it works
+
+
+
+
+1. Your app authenticates with the Auth0 Authorization Server using its Client ID and Client Secret ([**/oauth/token** endpoint](/api/authentication?http#client-credentials-flow)).
+2. Your Auth0 Authorization Server validates the Client ID and Client Secret.
+3. Your Auth0 Authorization Server responds with an Access Token.
+4. Your application can use the Access Token to call an API on behalf of itself.
+5. The API responds with requested data.
+
+
+## How to implement it
+
+The easiest way to implement the Client Credentials Flow is to follow our [Backend Quickstarts](/quickstart/backend).
+
+You can also follow our tutorial to use our API endpoints to [Call Your API Using the Client Credentials Flow](/flows/guides/client-credentials/call-api-client-credentials).
+
+## Keep reading
+
+- Learn how to personalize your user's login experience using [rules](/rules) and [hooks](/hooks)
+- Learn more about [tokens](/tokens) and [token storage](/tokens/concepts/token-storage)
+- Explore [Which OAuth 2.0 Flow Should I Use?](/api-auth/which-oauth-flow-to-use)
\ No newline at end of file
diff --git a/articles/flows/concepts/device-auth.md b/articles/flows/concepts/device-auth.md
new file mode 100644
index 0000000000..99eddae8b6
--- /dev/null
+++ b/articles/flows/concepts/device-auth.md
@@ -0,0 +1,63 @@
+---
+title: Device Authorization Flow
+description: Learn how the Device Authorization flow works and why you should use it for input-constrained devices, such as smart TVs and media consoles. For use with native apps.
+topics:
+ - input-constrained-devices
+ - device-flow
+ - api-authorization
+ - grants
+ - flows
+ - authorization
+ - mobile-apps
+ - desktop-apps
+ - native-apps
+contentType: concept
+useCase:
+ - add-login
+ - secure-api
+ - call-api
+---
+# Device Authorization Flow
+
+With input-constrained devices that connect to the internet, rather than authenticate the user directly, the device asks the user to go to a link on their computer or smartphone and authorize the device. This avoids a poor user experience for devices that do not have an easy way to enter text. To do this, device apps use the Device Authorization Flow (ratified in [OAuth 2.0](https://tools.ietf.org/html/rfc8628)), in which they pass along their Client ID to initiate the authorization process and get a token.
+
+## How it works
+
+The Device Authorization Flow contains two different paths; one occurs on the device requesting authorization and the other occurs in a browser. The browser flow path, wherein a device code is bound to the session in the browser, occurs in parallel to part of the device flow path.
+
+
+
+### Device Flow
+
+1. The user starts the app on the device.
+2. The device app requests authorization from the Auth0 Authorization Server using its Client ID (**/oauth/device/code** endpoint).
+3. The Auth0 Authorization Server responds with a `device_code`, `user_code`, `verification_uri`, `verification_uri_complete` `expires_in` (lifetime in seconds for `device_code` and `user_code`), and polling `interval`.
+4. The device app asks the user to activate using their computer or smartphone. The app may accomplish this by:
+ - asking the user to visit the `verification_uri` and enter the `user_code` after displaying these values on-screen
+ - asking the user to interact with either a QR Code or shortened URL with embedded user code generated from the `verification_uri_complete`
+ - directly navigating to the verification page with embedded user code using `verification_uri_complete`, if running natively on a browser-based device
+5. The device app begins polling your Auth0 Authorization Server for an Access Token (**/oauth/token** endpoint) using the time period specified by `interval` and counting from receipt of the last polling request's response. The device app continues polling until either the user completes the browser flow path or the user code expires.
+6. When the user successfully completes the browser flow path, your Auth0 Authorization Server responds with an Access Token (and optionally, a Refresh Token). The device app should now forget its `device_code` because it will expire.
+7. Your device app can use the Access Token to call an API to access information about the user.
+8. The API responds with requested data.
+
+### Browser Flow
+
+1. The user visits the `verification_uri` on their computer, enters the `user_code` and confirms that the device that is being activated is displaying the `user_code`. If the user visits the `verification_uri_complete` by any other mechanism (such as by scanning a QR code), only the device confirmation will be needed.
+2. Your Auth0 Authorization Server redirects the user to the login and consent prompt, if needed.
+3. The user authenticates using one of the configured login options and may see a consent page asking to authorize the device app.
+4. Your device app is authorized to access the API.
+
+## How to implement it
+
+The easiest way to implement the Device Authorization Flow is to follow our tutorial: [Call API Using Device Authorization Flow](/flows/guides/device-auth/call-api-device-auth).
+
+## Force device reauthorization
+
+To force the user to reauthorize a device, you must revoke the [Refresh Token](/tokens/guides/revoke-refresh-tokens) assigned to the device. To learn how, see [Unlink Devices from Users](/dashboard/guides/users/unlink-user-devices). Note that the device will not be forced to reauthorize until the current Access Token expires and the application tries to use the revoked Refresh Token.
+
+## Keep reading
+
+- Learn how to personalize your user's login experience using [rules](/rules) and [hooks](/hooks)
+- Learn more about [tokens](/tokens) and [token storage](/tokens/concepts/token-storage)
+- Explore [Which OAuth 2.0 Flow Should I Use?](/api-auth/which-oauth-flow-to-use)
\ No newline at end of file
diff --git a/articles/flows/concepts/implicit.md b/articles/flows/concepts/implicit.md
new file mode 100644
index 0000000000..fd8a3d2f8f
--- /dev/null
+++ b/articles/flows/concepts/implicit.md
@@ -0,0 +1,59 @@
+---
+title: Implicit Flow with Form Post
+description: Learn how the Implicit flow with Form Post works and why you should use it for single-page apps (SPAs) that need only an ID Token to perform user authentication.
+topics:
+ - authorization-code
+ - implicit
+ - hybrid
+ - api-authorization
+ - grants
+ - authentication
+ - SPA
+ - single-page apps
+contentType: concept
+useCase:
+ - secure-api
+ - call-api
+ - add-login
+---
+# Implicit Flow with Form Post
+
+::: warning
+The [OAuth 2.0 BCP](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-09#section-2.1.2) states that you **should not** use the Implicit Flow to request [Access Tokens](/tokens/access-tokens) from the Authorization Server. For this reason, we recommend that you use the [Authorization Code Flow with PKCE](/flows/concepts/auth-code-pkce) if your single-page app (SPA) requires Access Tokens for [Cross-Origin Resource Sharing (CORS)](/cross-origin-authentication#what-is-cross-origin-authentication) requests (along with [Refresh Token Rotation](/tokens/concepts/refresh-token-rotation) if your SPA needs to maintain session).
+:::
+
+As an alternative to the [Authorization Code Flow](/flows/concepts/auth-code), the OAuth 2.0 spec includes the Implicit Flow intended for Public Clients, or applications which are unable to securely store Client Secrets. As part of the authorization response, the Implicit Flow returns an Access Token rather than an Authorization Code that must be exchanged at the token endpoint.
+
+While this is no longer considered a best practice for requesting Access Tokens, it does offer a streamlined workflow if the application needs only an ID Token to perform user authentication.
+
+## How it works
+
+In the Implicit Flow, issued tokens are short-lived, and Refresh Tokens are not available.
+
+::: warning
+You should use this flow for login-only use cases; if you need to request Access Tokens while logging the user in so you can call your API, use the [Authorization Code Flow with PKCE](/flows/concepts/auth-code-pkce).
+:::
+
+
+
+1. The user clicks **Login** in the app.
+2. Auth0's SDK redirects the user to the Auth0 Authorization Server (**/authorize** endpoint) passing along a `response_type` parameter of `id_token` that indicates the type of requested credential. It also passes along a `response_mode` parameter of `form_post` to ensure security.
+3. Your Auth0 Authorization Server redirects the user to the login and authorization prompt.
+4. The user authenticates using one of the configured login options and may see a consent page listing the permissions Auth0 will give to the app.
+5. Your Auth0 Authorization Server redirects the user back to the app with an ID Token.
+
+## How to implement it
+
+You can use our [Express OpenID Connect SDK](https://www.npmjs.com/package/express-openid-connect) to securely implement the Implicit Flow. If you use our [Javascript SDKs](/libraries), please ensure you are implementing mitigations that are appropriate for your architecture.
+
+::: note
+The [Auth0 Single-Page App SDK](/libraries/auth0-spa-js) and [Single-Page Quickstarts](/quickstart/spa) adhere to the new recommendations and use the [Authorization Code Flow with PKCE](/flows/concepts/auth-code-pkce).
+:::
+
+Finally, you can follow our tutorials to use our API endpoints to [Add Login Using the Implicit Flow with Form Post](/flows/guides/implicit/add-login-implicit).
+
+## Keep reading
+
+- Learn how to personalize your user's login experience using [rules](/rules) and [hooks](/hooks)
+- Learn more about [tokens](/tokens) and [token storage](/tokens/concepts/token-storage)
+- Explore [Which OAuth 2.0 Flow Should I Use?](/api-auth/which-oauth-flow-to-use)
\ No newline at end of file
diff --git a/articles/flows/guides/auth-code-pkce/add-login-auth-code-pkce.md b/articles/flows/guides/auth-code-pkce/add-login-auth-code-pkce.md
new file mode 100644
index 0000000000..03e57d2ac3
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/add-login-auth-code-pkce.md
@@ -0,0 +1,68 @@
+---
+title: Add Login Using the Authorization Code Flow with PKCE
+description: Learn how to add login to your native, mobile, or single-page application using the Authorization Code Flow with Proof Key for Code Exchange (PKCE).
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - authorization-code
+ - pkce
+ - native-apps
+ - mobile-apps
+ - single-page-apps
+contentType: tutorial
+useCase:
+ - add-login
+---
+# Add Login Using the Authorization Code Flow with PKCE
+
+::: note
+This tutorial will help you add login to your native, mobile, or single-page app using the Authorization Code Flow with PKCE. If you want to learn how the flow works and why you should use it, see [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce). If you want to learn to call your API from a native, mobile, or single-page app, see [Call Your API Using Authorization Code Flow with PKCE](/flows/guides/auth-code-pkce/call-api-auth-code-pkce).
+:::
+
+Auth0 makes it easy for your app to implement the Authorization Code Flow with Proof Key for Code Exchange (PKCE) using:
+
+* [Auth0 Mobile SDKs](/libraries#auth0-sdks) and [Auth0 Single-Page App SDK](/libraries/auth0-spa-js): The easiest way to implement the flow, which will do most of the heavy-lifting for you. Our [Mobile Quickstarts](/quickstart/native) and [Single-Page App Quickstarts](/quickstart/spa) will walk you through the process.
+* Authentication API: If you prefer to roll your own, keep reading to learn how to call our API directly.
+
+Following successful login, your application will have access to the user's [ID Token](/tokens/concepts/id-tokens) and [Access Token](/tokens/concepts/access-tokens). The ID Token will contain basic user profile information, and the Access Token can be used to call the Auth0 /userinfo endpoint or your own protected APIs.
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* [Register your Application with Auth0](/dashboard/guides/applications/register-app-native).
+ * Select an **Application Type** of **Native** or **Single-Page App**, depending on your application type.
+ * Add an **Allowed Callback URL** of **`YOUR_CALLBACK_URL`**. Your callback URL format will vary depending on your application type and platform. For details about the format for your application type and platform, see our [Native/Mobile Quickstarts](/quickstart/native) and [Single-Page App Quickstarts](/quickstart/spa).
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Authorization Code**.
+
+## Steps
+
+Each time your user chooses to authenticate you will need to:
+
+1. [Create a code verifier](#create-a-code-verifier):
+Generate a `code_verifier` that will be sent to Auth0 to request tokens.
+2. [Create a code challenge](#create-a-code-challenge):
+Generate a `code_challenge` from the `code_verifier` that will be sent to Auth0 to request an `authorization_code`.
+3. [Authorize the user](#authorize-the-user):
+Request the user's authorization and redirect back to your app with an `authorization_code`.
+4. [Request Tokens](#request-tokens):
+Exchange your `authorization_code` and `code_verifier` for tokens.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+<%= include('./includes/create-code-verifier') %>
+
+<%= include('./includes/create-code-challenge') %>
+
+<%= include('./includes/authorize-user-add-login') %>
+
+<%= include('./includes/request-tokens') %>
+
+<%= include('./includes/sample-use-cases-add-login') %>
+
+## Keep reading
+
+- [OAuth 2.0 framework](/protocols/oauth2)
+- [OpenID Connect (OIDC) protocol](/protocols/oidc)
+- [Tokens](/tokens)
diff --git a/articles/flows/guides/auth-code-pkce/call-api-auth-code-pkce.md b/articles/flows/guides/auth-code-pkce/call-api-auth-code-pkce.md
new file mode 100644
index 0000000000..8f737d50b0
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/call-api-auth-code-pkce.md
@@ -0,0 +1,79 @@
+---
+title: Call API Using Authorization Code Flow with PKCE
+description: Learn how to call your API from a native, mobile, or single-page application using the Authorization Code flow using Proof Key for Code Exchange (PKCE).
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - authorization-code
+ - pkce
+ - native-apps
+ - mobile-apps
+ - single-page-apps
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
+---
+# Call Your API Using the Authorization Code Flow with PKCE
+
+::: note
+This tutorial will help you call your own API from a native, mobile, or single-page app using the Authorization Code Flow with PKCE. If you want to learn how the flow works and why you should use it, see [Authorization Code Flow with Proof Key for Code Exchange (PKCE)](/flows/concepts/auth-code-pkce). If you want to learn to add login to your native, mobile, or single-page app, see [Add Login Using Authorization Code Flow with PKCE](/flows/guides/auth-code-pkce/add-login-auth-code-pkce).
+:::
+
+Auth0 makes it easy for your app to implement the Authorization Code Flow with Proof Key for Code Exchange (PKCE) using:
+
+* [Auth0 Mobile SDKs](/libraries#auth0-sdks) and [Auth0 Single-Page App SDK](/libraries/auth0-spa-js): The easiest way to implement the flow, which will do most of the heavy-lifting for you. Our [Mobile Quickstarts](/quickstart/native) and [Single-Page App Quickstarts](/quickstart/spa) will walk you through the process.
+* Authentication API: If you prefer to roll your own, keep reading to learn how to call our API directly.
+
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* [Register the Application with Auth0](/dashboard/guides/applications/register-app-native).
+ * Select an **Application Type** of **Native** or **Single-Page App**, depending on your application type.
+ * Add an **Allowed Callback URL** of **`YOUR_CALLBACK_URL`**. Your callback URL format will vary depending on your application type and platform. For details about the format for your application type and platform, see our [Native/Mobile Quickstarts](/quickstart/native) and [Single-Page App Quickstarts](/quickstart/spa).
+ * Make sure the Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Authorization Code**.
+ * If you want your Application to be able to use [Refresh Tokens](/tokens/concepts/refresh-tokens), make sure the Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Refresh Token**.
+
+* [Register your API with Auth0](/architecture-scenarios/mobile-api/part-2#create-the-api)
+ * If you want your API to receive Refresh Tokens to allow it to obtain new tokens when the previous ones expire, enable **Allow Offline Access**.
+
+## Steps
+
+1. [Create a code verifier](#create-a-code-verifier):
+Generate a `code_verifier` that will be sent to Auth0 to request tokens.
+2. [Create a code challenge](#create-a-code-challenge):
+Generate a `code_challenge` from the `code_verifier` that will be sent to Auth0 to request an `authorization_code`.
+3. [Authorize the user](#authorize-the-user):
+Request the user's authorization and redirect back to your app with an `authorization_code`.
+4. [Request Tokens](#request-tokens):
+Exchange your `authorization_code` and `code_verifier` for tokens.
+5. [Call your API](#call-your-api):
+Use the retrieved Access Token to call your API.
+6. [Refresh Tokens](#refresh-tokens):
+Use a Refresh Token to request new tokens when the existing ones expire.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+
+<%= include('./includes/create-code-verifier') %>
+
+<%= include('./includes/create-code-challenge') %>
+
+<%= include('./includes/authorize-user-call-api') %>
+
+<%= include('./includes/request-tokens') %>
+
+<%= include('./includes/call-api') %>
+
+<%= include('./includes/refresh-tokens') %>
+
+<%= include('./includes/sample-use-cases-call-api') %>
+
+## Keep reading
+
+- [OAuth 2.0 framework](/protocols/oauth2)
+- [OpenID Connect (OIDC) protocol](/protocols/oidc)
+- [Tokens](/tokens)
diff --git a/articles/flows/guides/auth-code-pkce/includes/authorize-user-add-login.md b/articles/flows/guides/auth-code-pkce/includes/authorize-user-add-login.md
new file mode 100644
index 0000000000..31591db0b8
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/authorize-user-add-login.md
@@ -0,0 +1,63 @@
+## Authorize the User
+
+Once you've created the `code_verifier` and the `code_challenge`, you'll need to get the user's authorization. This is technically the beginning of the authorization flow, and this step may include one or more of the following processes:
+
+* Authenticating the user;
+* Redirecting the user to an Identity Provider to handle authentication;
+* Checking for active Single Sign-on (SSO) sessions;
+* Obtaining user consent for the requested permission level, unless consent has been previously given.
+
+To authorize the user, your app must send the user to the [authorization URL](/api/authentication#authorization-code-grant-pkce-), including the `code_challenge` you generated in the previous step and the method you used to generate the `code_challenge`.
+
+
+### Example authorization URL
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256&
+ client_id=${account.clientId}&
+ redirect_uri=YOUR_CALLBACK_URL&
+ scope=SCOPE&
+ state=STATE
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `response_type` | Denotes the kind of credential that Auth0 will return (`code` or `token`). For this flow, the value must be `code`. |
+| `code_challenge` | Generated challenge from the `code_verifier`. |
+| `code_challenge_method` | Method used to generate the challenge (e.g., S256). The PKCE spec defines two methods, `S256` and `plain`, the former is used in this example and is the **only** one supported by Auth0 since the latter is discouraged. |
+| `client_id` |Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the `code` URL parameter. You must specify this URL as a valid callback URL in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings).
**Warning:** Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments. |
+| `scope` | Specifies the [scopes](/scopes) for which you want to request authorization, which dictate which claims (or user attributes) you want returned. These must be separated by a space. To get an ID Token in the response, you need to specify a scope of at least `openid`. If you want to return the user's full profile, you can request `openid profile`. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `email`, or [custom claims](/tokens/concepts/jwt-claims#custom-claims) conforming to a [namespaced format](/tokens/guides/create-namespaced-custom-claims). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [Application Settings](${manage_url}/#/applications)). |
+| `state` | (recommended) An opaque arbitrary alphanumeric string your app adds to the initial request that Auth0 includes when redirecting back to your application. To see how to use this value to prevent cross-site request forgery (CSRF) attacks, see [Mitigate CSRF Attacks With State Parameters](/protocols/oauth2/mitigate-csrf-attacks). |
+| `connection` | (optional) Forces the user to sign in with a specific connection. For example, you can pass a value of `github` to send the user directly to GitHub to log in with their GitHub account. When not specified, the user sees the Auth0 Lock screen with all configured connections. You can see a list of your configured connections on the **Connections** tab of your application. |
+
+
+As an example, your HTML snippet for your authorization URL when adding login to your app might look like:
+
+```html
+
+ Sign In
+
+```
+
+
+### Response
+
+If all goes well, you'll receive an `HTTP 302` response. The authorization code is included at the end of the URL:
+
+```text
+HTTP/1.1 302 Found
+Location: YOUR_CALLBACK_URL?code=AUTHORIZATION_CODE&state=xyzABC123
+```
diff --git a/articles/flows/guides/auth-code-pkce/includes/authorize-user-call-api.md b/articles/flows/guides/auth-code-pkce/includes/authorize-user-call-api.md
new file mode 100644
index 0000000000..cbb11d6cfc
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/authorize-user-call-api.md
@@ -0,0 +1,71 @@
+## Authorize the User
+
+Once you've created the `code_verifier` and the `code_challenge`, you'll need to get the user's authorization. This is technically the beginning of the authorization flow, and this step may include one or more of the following processes:
+
+* Authenticating the user;
+* Redirecting the user to an Identity Provider to handle authentication;
+* Checking for active Single Sign-on (SSO) sessions;
+* Obtaining user consent for the requested permission level, unless consent has been previously given.
+
+To authorize the user, your app must send the user to the [authorization URL](/api/authentication#authorization-code-grant-pkce-), including the `code_challenge` you generated in the previous step and the method you used to generate the `code_challenge`.
+
+
+### Example authorization URL
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256&
+ client_id=${account.clientId}&
+ redirect_uri=YOUR_CALLBACK_URL&
+ scope=SCOPE&
+ audience=API_AUDIENCE&
+ state=STATE
+```
+
+#### Parameters
+
+Note that for authorizing a user when calling a custom API, you:
+
+- must include an audience parameter
+- can include additional scopes supported by the target API
+
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `response_type` | Denotes the kind of credential that Auth0 will return (`code` or `token`). For this flow, the value must be `code`. |
+| `code_challenge` | Generated challenge from the `code_verifier`. |
+| `code_challenge_method` | Method used to generate the challenge (e.g., S256). The PKCE spec defines two methods, `S256` and `plain`, the former is used in this example and is the **only** one supported by Auth0 since the latter is discouraged. |
+| `client_id` |Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the `code` URL parameter. You must specify this URL as a valid callback URL in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings).
**Warning:** Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments. |
+| `scope` | The [scopes](/scopes) for which you want to request authorization. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, [custom claims](/tokens/concepts/jwt-claims#custom-claims) conforming to a [namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (e.g., `read:contacts`). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [Application Settings](${manage_url}/#/apis)). |
+|`audience` | The unique identifier of the API your mobile app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial. |
+| `state` | (recommended) An opaque arbitrary alphanumeric string your app adds to the initial request that Auth0 includes when redirecting back to your application. To see how to use this value to prevent cross-site request forgery (CSRF) attacks, see [Mitigate CSRF Attacks With State Parameters](/protocols/oauth2/mitigate-csrf-attacks). |
+
+
+As an example, your HTML snippet for your authorization URL when calling an API might look like:
+
+```html
+
+ Sign In
+
+```
+
+
+### Response
+
+If all goes well, you'll receive an `HTTP 302` response. The authorization code is included at the end of the URL:
+
+```text
+HTTP/1.1 302 Found
+Location: YOUR_CALLBACK_URL?code=AUTHORIZATION_CODE&state=xyzABC123
+```
diff --git a/articles/flows/guides/auth-code-pkce/includes/call-api.md b/articles/flows/guides/auth-code-pkce/includes/call-api.md
new file mode 100644
index 0000000000..95c675e3c9
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/call-api.md
@@ -0,0 +1,15 @@
+## Call your API
+
+To call your API from a native/mobile application, the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.
+
+
+ ```har
+{
+ "method": "GET",
+ "url": "https://myapi.com/api",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer ACCESS_TOKEN" }
+ ]
+}
+```
diff --git a/articles/flows/guides/auth-code-pkce/includes/create-code-challenge.md b/articles/flows/guides/auth-code-pkce/includes/create-code-challenge.md
new file mode 100644
index 0000000000..8bd378a10c
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/create-code-challenge.md
@@ -0,0 +1,70 @@
+## Create a Code Challenge
+
+Generate a `code_challenge` from the `code_verifier` that will be sent to Auth0 to request an `authorization_code`.
+
+
+
diff --git a/articles/flows/guides/auth-code-pkce/includes/create-code-verifier.md b/articles/flows/guides/auth-code-pkce/includes/create-code-verifier.md
new file mode 100644
index 0000000000..a05a231f8b
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/create-code-verifier.md
@@ -0,0 +1,60 @@
+## Create a Code Verifier
+
+Create a `code_verifier`, which is a cryptographically-random key that will eventually be sent to Auth0 to request tokens.
+
+
+
diff --git a/articles/flows/guides/auth-code-pkce/includes/refresh-tokens.md b/articles/flows/guides/auth-code-pkce/includes/refresh-tokens.md
new file mode 100644
index 0000000000..0946684b81
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/refresh-tokens.md
@@ -0,0 +1,66 @@
+## Refresh Tokens
+
+You have already received a Refresh Token if you've been following this tutorial and completed the following:
+
+* configured your API to allow offline access
+* included the `offline_access` scope when you initiated the authentication request through the [authorize](/api/authentication/reference#authorize-application) endpoint
+
+You can use the Refresh Token to get a new Access Token. Usually, a user will need a new Access Token only after the previous one expires or when gaining access to a new resource for the first time. It's bad practice to call the endpoint to get a new Access Token every time you call an API, and Auth0 maintains rate limits that will throttle the amount of requests to the endpoint that can be executed using the same token from the same IP.
+
+To refresh your token, make a `POST` request to the `/oauth/token` endpoint in the Authentication API, using `grant_type=refresh_token`.
+
+### Example POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "refresh_token"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "refresh_token",
+ "value": "YOUR_REFRESH_TOKEN"
+ }
+ ]
+ }
+}
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "refresh_token". |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `refresh_token` | The Refresh Token to use. |
+| `scope` | (Optional) A space-delimited list of requested scope permissions. If not sent, the original scopes will be used; otherwise you can request a reduced set of scopes. Note that this must be URL encoded. |
+
+### Response
+
+If all goes well, you'll receive an `HTTP 200` response with a payload containing a new `access_token`, its lifetime in seconds (`expires_in`), granted `scope` values, and `token_type`. If the scope of the initial token included `openid`, then the response will also include a new `id_token`:
+
+```json
+{
+ "access_token": "eyJ...MoQ",
+ "expires_in": 86400,
+ "scope": "openid offline_access",
+ "id_token": "eyJ...0NE",
+ "token_type": "Bearer"
+}
+```
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Tokens](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
diff --git a/articles/flows/guides/auth-code-pkce/includes/request-tokens.md b/articles/flows/guides/auth-code-pkce/includes/request-tokens.md
new file mode 100644
index 0000000000..71ee43fb40
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/request-tokens.md
@@ -0,0 +1,78 @@
+## Request Tokens
+
+Now that you have an Authorization Code, you must exchange it for tokens. Using the extracted Authorization Code (`code`) from the previous step, you will need to `POST` to the [token URL](/api/authentication#authorization-code-pkce-) sending along the `code_verifier`.
+
+### Example POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "code_verifier",
+ "value": "YOUR_GENERATED_CODE_VERIFIER"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "${account.callback}"
+ }
+ ]
+ }
+}
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "authorization_code". |
+| `code_verifier` | The cryptographically-random key that was generated in the first step of this tutorial. |
+| `code` | The `authorization_code` retrieved in the previous step of this tutorial. |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `redirect_uri` | The valid callback URL set in your Application settings. This must exactly match the `redirect_uri` passed to the authorization URL in the previous step of this tutorial. Note that this must be URL encoded. |
+
+
+### Response
+
+If all goes well, you'll receive an HTTP 200 response with a payload containing `access_token`, `refresh_token`, `id_token`, and `token_type` values:
+
+```json
+{
+ "access_token":"eyJz93a...k4laUWw",
+ "refresh_token":"GEbRxBN...edjnXbL",
+ "id_token":"eyJ0XAi...4faeEoQ",
+ "token_type":"Bearer",
+ "expires_in":86400
+}
+```
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Tokens](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
+
+[ID Tokens](/tokens/concepts/id-tokens) contain user information that must be [decoded and extracted](/tokens/id-tokens#id-token-payload).
+
+[Access Tokens](/tokens/concepts/access-token) are used to call the [Auth0 Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or another API. If you are calling your own API, the first thing your API will need to do is [verify the Access Token](/tokens/guides/validate-access-tokens).
+
+[Refresh Tokens](/tokens/concepts/refresh-tokens) are used to obtain a new Access Token or ID Token after the previous one has expired. The `refresh_token` will only be present in the response if you included the `offline_access` scope and enabled __Allow Offline Access__ for your API in the Dashboard.
+
+::: warning
+Refresh Tokens must be stored securely since they allow a user to remain authenticated essentially forever.
+:::
diff --git a/articles/flows/guides/auth-code-pkce/includes/sample-use-cases-add-login.md b/articles/flows/guides/auth-code-pkce/includes/sample-use-cases-add-login.md
new file mode 100644
index 0000000000..e72b60344a
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/sample-use-cases-add-login.md
@@ -0,0 +1,94 @@
+## Sample Use Cases
+
+### Basic Authentication Request
+
+This example shows the most basic request you can make when authorizing the user in step 1. It displays the Auth0 login screen and allows the user to sign in with any of your configured connections:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256&
+ client_id=${account.clientId}&
+ redirect_uri=YOUR_CALLBACK_URL&
+ scope=openid
+```
+
+Now, when you [request tokens](/flows/guides/auth-code-pkce/add-login-auth-code-pkce#request-tokens), your ID Token will contain the most basic claims. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "iss": "https://auth0pnp.auth0.com/",
+ "sub": "auth0|581...",
+ "aud": "xvt9...",
+ "exp": 1478112929,
+ "iat": 1478076929
+}
+```
+
+### Request the User's Name and Profile Picture
+
+In addition to the usual user authentication, this example shows how to request additional user details, such as name and picture.
+
+To request the user's name and picture, you need to add the appropriate scopes when authorizing the user in step 3:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256&
+ client_id=${account.clientId}&
+ redirect_uri=YOUR_CALLBACK_URL&
+ scope=openid%20name%20picture&
+ state=STATE
+```
+
+Now, when you [request tokens](/flows/guides/auth-code-pkce/add-login-auth-code-pkce#request-tokens), your ID Token will contain the requested name and picture claims. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "name": "auth0user@...",
+ "picture": "https://example.com/profile-pic.png",
+ "iss": "https://auth0user.auth0.com/",
+ "sub": "auth0|581...",
+ "aud": "xvt...",
+ "exp": 1478113129,
+ "iat": 1478077129
+}
+```
+
+### Request a User Log In with GitHub
+
+In addition to the usual user authentication, this example shows how to send users directly to a social identity provider, such as GitHub. For this example to work, you will first need to [configure the appropriate connection in the Auth0 Dashboard](${manage_url}/#/connections/social) and get the connection name from the **Settings** tab.
+
+To send users directly to the GitHub login screen, you need to pass the `connection` parameter and set its value to the connection name (in this case, `github`) when authorizing the user in step 3:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ code_challenge=CODE_CHALLENGE&
+ code_challenge_method=S256&
+ client_id=${account.clientId}&
+ redirect_uri=YOUR_CALLBACK_URL&
+ scope=openid%20name%20picture&
+ state=STATE&
+ connection=github
+```
+
+Now, when you [request tokens](/flows/guides/auth-code-pkce/add-login-auth-code-pkce#request-tokens), your ID Token will contain a `sub` claim with the user's unique ID returned from GitHub. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "name": "John Smith",
+ "picture": "https://avatars.example.com",
+ "email": "jsmith@...",
+ "email_verified": true,
+ "iss": "https://auth0user.auth0.com/",
+ "sub": "github|100...",
+ "aud": "xvt...",
+ "exp": 1478114742,
+ "iat": 1478078742
+}
+```
+
+For a list of possible connections, see [Identity Providers Supported by Auth0](/identityproviders).
diff --git a/articles/flows/guides/auth-code-pkce/includes/sample-use-cases-call-api.md b/articles/flows/guides/auth-code-pkce/includes/sample-use-cases-call-api.md
new file mode 100644
index 0000000000..7cfe4d986a
--- /dev/null
+++ b/articles/flows/guides/auth-code-pkce/includes/sample-use-cases-call-api.md
@@ -0,0 +1,29 @@
+## Sample Use Cases
+
+### Customize Tokens
+
+You can use [Rules](/rules) to change the returned scopes of Access Tokens and/or add claims to Access and ID Tokens. To do so, add the following rule, which will run after the user authenticates:
+
+```javascript
+function(user, context, callback) {
+
+ // add custom claims to Access Token and ID Token
+ context.accessToken['http://foo/bar'] = 'value';
+ context.idToken['http://fiz/baz'] = 'some other value';
+
+ // change scope
+ context.accessToken.scope = ['array', 'of', 'strings'];
+
+ callback(null, user, context);
+}
+```
+
+Scopes will be available in the token after all rules have run.
+
+::: panel-warning Namespacing Custom Claims
+Auth0 returns profile information in a [structured claim format as defined by the OpenID Connect (OIDC) specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that custom claims added to ID Tokens or Access Tokens must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims.
+:::
+
+### View Sample Application: Mobile App + API
+
+For an sample implementation, see the [Mobile + API](/architecture-scenarios/application/mobile-api) architecture scenario. This series of tutorials is accompanied by a code sample that you can access in [GitHub](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets).
diff --git a/articles/flows/guides/auth-code/add-login-auth-code.md b/articles/flows/guides/auth-code/add-login-auth-code.md
new file mode 100644
index 0000000000..e3824d399e
--- /dev/null
+++ b/articles/flows/guides/auth-code/add-login-auth-code.md
@@ -0,0 +1,58 @@
+---
+title: Add Login Using the Authorization Code Flow
+description: Learn how to add login to your regular web application using the Authorization Code Flow.
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - authorization-code
+ - regular-web-apps
+contentType: tutorial
+useCase:
+ - add-login
+---
+# Add Login Using the Authorization Code Flow
+
+::: note
+This tutorial will help you add login to your regular web application using the Authorization Code Flow. If you want to learn how the flow works and why you should use it, see [Authorization Code Flow](/flows/concepts/auth-code). If you want to learn to call your API from a regular web app, see [Call Your API Using the Authorization Code Flow](/flows/guides/auth-code/call-api-auth-code).
+:::
+
+Auth0 makes it easy for your app to implement the Authorization Code Flow using:
+
+* [Regular Web App Quickstarts](/quickstart/webapp): The easiest way to implement the flow.
+* Authentication API: If you prefer to roll your own, keep reading to learn how to call our API directly.
+
+Following successful login, your application will have access to the user's [ID Token](/tokens/concepts/id-tokens) and [Access Token](/tokens/concepts/access-tokens). The ID Token will contain basic user profile information, and the Access Token can be used to call the Auth0 /userinfo endpoint or your own protected APIs.
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* [Register your Application with Auth0](/dashboard/guides/applications/register-app-regular-web).
+ * Select an **Application Type** of **Regular Web Apps**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Authorization Code**.
+
+
+## Steps
+
+1. [Authorize the user](#authorize-the-user):
+Request the user's authorization and redirect back to your app with an `authorization_code`.
+2. [Request Tokens](#request-tokens):
+Exchange your `authorization_code` for tokens.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+
+<%= include('./includes/authorize-user-add-login') %>
+
+<%= include('./includes/request-tokens') %>
+
+<%= include('./includes/sample-use-cases-add-login') %>
+
+## Keep reading
+
+- [OAuth 2.0 framework](/protocols/oauth2)
+- [OpenID Connect (OIDC) protocol](/protocols/oidc)
+- [Tokens](/tokens)
+
diff --git a/articles/flows/guides/auth-code/call-api-auth-code.md b/articles/flows/guides/auth-code/call-api-auth-code.md
new file mode 100644
index 0000000000..51e879faa7
--- /dev/null
+++ b/articles/flows/guides/auth-code/call-api-auth-code.md
@@ -0,0 +1,68 @@
+---
+title: Call API Using the Authorization Code Flow
+description: Learn how to call your own API from regular web apps using the Authorization Code Flow.
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - authorization-code
+ - regular-web-apps
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
+---
+# Call Your API Using the Authorization Code Flow
+
+::: note
+This tutorial will help you call your own API using the Authorization Code Flow. If you want to learn how the flow works and why you should use it, see [Authorization Code Flow](/flows/concepts/auth-code). If you want to learn to add login to your regular web app, see [Add Login Using the Authorization Code Flow](/flows/guides/auth-code/add-login-auth-code).
+:::
+
+Auth0 makes it easy for your app to implement the Authorization Code Flow using:
+
+* [Regular Web App Quickstarts](/quickstart/webapp): The easiest way to implement the flow.
+* Authentication API: If you prefer to roll your own, keep reading to learn how to call our API directly.
+
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* [Register your Application with Auth0](/dashboard/guides/applications/register-app-regular-web).
+ * Select an **Application Type** of **Regular Web Apps**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Authorization Code**.
+ * If you want your Application to be able to use [Refresh Tokens](/tokens/concepts/refresh-tokens), make sure the Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Refresh Token**.
+
+* [Register your API with Auth0](/architecture-scenarios/mobile-api/part-2#create-the-api)
+ * If you want your API to receive Refresh Tokens to allow it to obtain new tokens when the previous ones expire, enable **Allow Offline Access**.
+
+## Steps
+
+1. [Authorize the user](#authorize-the-user):
+Request the user's authorization and redirect back to your app with an authorization code.
+2. [Request Tokens](#request-tokens):
+Exchange your authorization code for tokens.
+3. [Call your API](#call-your-api):
+Use the retrieved Access Token to call your API.
+4. [Refresh Tokens](#refresh-tokens):
+Use a Refresh Token to request new tokens when the existing ones expire.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+
+<%= include('./includes/authorize-user-call-api') %>
+
+<%= include('./includes/request-tokens') %>
+
+<%= include('./includes/call-api') %>
+
+<%= include('./includes/refresh-tokens') %>
+
+<%= include('./includes/sample-use-cases-call-api') %>
+
+## Keep reading
+
+- [OAuth 2.0 framework](/protocols/oauth2)
+- [OpenID Connect (OIDC) protocol](/protocols/oidc)
+- [Tokens](/tokens)
diff --git a/articles/flows/guides/auth-code/includes/authorize-user-add-login.md b/articles/flows/guides/auth-code/includes/authorize-user-add-login.md
new file mode 100644
index 0000000000..2d9c1a18ff
--- /dev/null
+++ b/articles/flows/guides/auth-code/includes/authorize-user-add-login.md
@@ -0,0 +1,53 @@
+## Authorize the User
+
+To begin the flow, you'll need to get the user's authorization. This step may include one or more of the following processes:
+
+* Authenticating the user;
+* Redirecting the user to an Identity Provider to handle authentication;
+* Obtaining user consent for the requested permission level, unless consent has been previously given.
+
+To authorize the user, your app must send the user to the [authorization URL](/api/authentication#authorization-code-flow).
+
+### Example authorization URL
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=SCOPE&
+ state=STATE
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `response_type` | Denotes the kind of credential that Auth0 will return (`code` or `token`). For this flow, the value must be `code`. |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the `code` URL parameter. You must specify this URL as a valid callback URL in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings).
**Warning:** Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments. |
+| `scope` | Specifies the [scopes](/scopes) for which you want to request authorization, which dictate which claims (or user attributes) you want returned. These must be separated by a space. To get an ID Token in the response, you need to specify a scope of at least `openid`. If you want to return the user's full profile, you can request `openid profile`. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `email`, or [custom claims](/tokens/concepts/jwt-claims#custom-claims) conforming to a [namespaced format](/tokens/guides/create-namespaced-custom-claims). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [Application Settings](${manage_url}/#/applications)). |
+| `state` | (recommended) An opaque arbitrary alphanumeric string your app adds to the initial request that Auth0 includes when redirecting back to your application. To see how to use this value to prevent cross-site request forgery (CSRF) attacks, see [Mitigate CSRF Attacks With State Parameters](/protocols/oauth2/mitigate-csrf-attacks). |
+| `connection` | (optional) Forces the user to sign in with a specific connection. For example, you can pass a value of `github` to send the user directly to GitHub to log in with their GitHub account. When not specified, the user sees the Auth0 Lock screen with all configured connections. You can see a list of your configured connections on the **Connections** tab of your application. |
+
+As an example, your HTML snippet for your authorization URL when adding login to your app might look like:
+
+```html
+
+ Sign In
+
+```
+
+### Response
+
+If all goes well, you'll receive an `HTTP 302` response. The authorization code is included at the end of the URL:
+
+```text
+HTTP/1.1 302 Found
+Location: ${account.callback}?code=AUTHORIZATION_CODE&state=xyzABC123
+```
diff --git a/articles/flows/guides/auth-code/includes/authorize-user-call-api.md b/articles/flows/guides/auth-code/includes/authorize-user-call-api.md
new file mode 100644
index 0000000000..69a5106534
--- /dev/null
+++ b/articles/flows/guides/auth-code/includes/authorize-user-call-api.md
@@ -0,0 +1,63 @@
+## Authorize the User
+
+To begin the flow, you'll need to get the user's authorization. This step may include one or more of the following processes:
+
+* Authenticating the user;
+* Redirecting the user to an Identity Provider to handle authentication;
+* Checking for active Single Sign-on (SSO) sessions;
+* Obtaining user consent for the requested permission level, unless consent has been previously given.
+
+To authorize the user, your app must send the user to the [authorization URL](/api/authentication#authorization-code-grant).
+
+
+### Example authorization URL
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=SCOPE&
+ audience=API_AUDIENCE&
+ state=STATE
+```
+
+#### Parameters
+
+Note that for authorizing a user when calling a custom API, you:
+
+- must include an audience parameter
+- can include additional scopes supported by the target API
+
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `response_type` | Denotes the kind of credential that Auth0 will return (`code` or `token`). For this flow, the value must be `code`. |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. The Authorization Code will be available in the `code` URL parameter. You must specify this URL as a valid callback URL in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings).
**Warning:** Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments. |
+| `scope` | Specifies the [scopes](/scopes) for which you want to request authorization, which dictate which claims (or user attributes) you want returned. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` or `email`, [custom claims](/tokens/concepts/jwt-claims#custom-claims) conforming to a [namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (e.g., `read:contacts`). Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [Application Settings](${manage_url}/#/applications)). |
+| `audience` | The unique identifier of the API your web app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial. |
+| `state` | (recommended) An opaque arbitrary alphanumeric string your app adds to the initial request that Auth0 includes when redirecting back to your application. To see how to use this value to prevent cross-site request forgery (CSRF) attacks, see [Mitigate CSRF Attacks With State Parameters](/protocols/oauth2/mitigate-csrf-attacks). |
+
+As an example, your HTML snippet for your authorization URL when calling an API might look like:
+
+```html
+
+ Sign In
+
+```
+
+### Response
+
+If all goes well, you'll receive an `HTTP 302` response. The authorization code is included at the end of the URL:
+
+```text
+HTTP/1.1 302 Found
+Location: ${account.callback}?code=AUTHORIZATION_CODE&state=xyzABC123
+```
diff --git a/articles/flows/guides/auth-code/includes/call-api.md b/articles/flows/guides/auth-code/includes/call-api.md
new file mode 100644
index 0000000000..c621fb6d86
--- /dev/null
+++ b/articles/flows/guides/auth-code/includes/call-api.md
@@ -0,0 +1,15 @@
+## Call your API
+
+To call your API from a regular web application, the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.
+
+
+ ```har
+{
+ "method": "GET",
+ "url": "https://myapi.com/api",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer ACCESS_TOKEN" }
+ ]
+}
+```
diff --git a/articles/flows/guides/auth-code/includes/refresh-tokens.md b/articles/flows/guides/auth-code/includes/refresh-tokens.md
new file mode 100644
index 0000000000..4ebc667073
--- /dev/null
+++ b/articles/flows/guides/auth-code/includes/refresh-tokens.md
@@ -0,0 +1,66 @@
+## Refresh Tokens
+
+You have already received a Refresh Token if you've been following this tutorial and completed the following:
+
+* configured your API to allow offline access
+* included the `offline_access` scope when you initiated the authentication request through the [authorize](/api/authentication/reference#authorize-application) endpoint
+
+You can use the Refresh Token to get a new Access Token. Usually, a user will need a new Access Token only after the previous one expires or when gaining access to a new resource for the first time. It's bad practice to call the endpoint to get a new Access Token every time you call an API, and Auth0 maintains rate limits that will throttle the amount of requests to the endpoint that can be executed using the same token from the same IP.
+
+To refresh your token, make a `POST` request to the `/oauth/token` endpoint in the Authentication API, using `grant_type=refresh_token`.
+
+### Example POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "refresh_token"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "refresh_token",
+ "value": "YOUR_REFRESH_TOKEN"
+ }
+ ]
+ }
+}
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "refresh_token". |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `refresh_token` | The Refresh Token to use. |
+| `scope` | (optional) A space-delimited list of requested scope permissions. If not sent, the original scopes will be used; otherwise you can request a reduced set of scopes. Note that this must be URL encoded. |
+
+### Response
+
+If all goes well, you'll receive an `HTTP 200` response with a payload containing a new `access_token`, its lifetime in seconds (`expires_in`), granted `scope` values, and `token_type`. If the scope of the initial token included `openid`, then the response will also include a new `id_token`:
+
+```json
+{
+ "access_token": "eyJ...MoQ",
+ "expires_in": 86400,
+ "scope": "openid offline_access",
+ "id_token": "eyJ...0NE",
+ "token_type": "Bearer"
+}
+```
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Tokens](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
diff --git a/articles/flows/guides/auth-code/includes/request-tokens.md b/articles/flows/guides/auth-code/includes/request-tokens.md
new file mode 100644
index 0000000000..6a468fe06c
--- /dev/null
+++ b/articles/flows/guides/auth-code/includes/request-tokens.md
@@ -0,0 +1,78 @@
+## Request Tokens
+
+Now that you have an Authorization Code, you must exchange it for tokens. Using the extracted Authorization Code (`code`) from the previous step, you will need to `POST` to the [token URL](/api/authentication#authorization-code).
+
+### Example POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "${account.callback}"
+ }
+ ]
+ }
+}
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "authorization_code". |
+| `code` | The `authorization_code` retrieved in the previous step of this tutorial. |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `client_secret` | Your application's Client Secret. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `redirect_uri` | The valid callback URL set in your Application settings. This must exactly match the `redirect_uri` passed to the authorization URL in the previous step of this tutorial. Note that this must be URL encoded. |
+
+
+### Response
+
+If all goes well, you'll receive an HTTP 200 response with a payload containing `access_token`, `refresh_token`, `id_token`, and `token_type` values:
+
+```js
+{
+ "access_token": "eyJz93a...k4laUWw",
+ "refresh_token": "GEbRxBN...edjnXbL",
+ "id_token": "eyJ0XAi...4faeEoQ",
+ "token_type": "Bearer"
+}
+```
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Token](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
+
+[ID Tokens](/tokens/concepts/id-tokens) contain user information that must be [decoded and extracted](/tokens/id-tokens#id-token-payload).
+
+[Access Tokens](/tokens/concepts/access-tokens) are used to call the [Auth0 Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or another API. If you are calling your own API, the first thing your API will need to do is [verify the Access Token](/tokens/guides/validate-access-tokens).
+
+[Refresh Tokens](/tokens/concepts/refresh-tokens) are used to obtain a new Access Token or ID Token after the previous one has expired. The `refresh_token` will only be present in the response if you included the `offline_access` scope and enabled __Allow Offline Access__ for your API in the Dashboard.
+
+::: warning
+Refresh Tokens must be stored securely since they allow a user to remain authenticated essentially forever.
+:::
diff --git a/articles/flows/guides/auth-code/includes/sample-use-cases-add-login.md b/articles/flows/guides/auth-code/includes/sample-use-cases-add-login.md
new file mode 100644
index 0000000000..f0a6478f24
--- /dev/null
+++ b/articles/flows/guides/auth-code/includes/sample-use-cases-add-login.md
@@ -0,0 +1,87 @@
+## Sample Use Cases
+
+### Basic Authentication Request
+
+This example shows the most basic request you can make when authorizing the user in step 1. It displays the Auth0 login screen and allows the user to sign in with any of your configured connections:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=openid
+```
+
+Now, when you [request tokens](/flows/guides/auth-code/add-login-auth-code#request-tokens), your ID Token will contain the most basic claims. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "iss": "https://auth0pnp.auth0.com/",
+ "sub": "auth0|581...",
+ "aud": "xvt9...",
+ "exp": 1478112929,
+ "iat": 1478076929
+}
+```
+
+### Request the User's Name and Profile Picture
+
+In addition to the usual user authentication, this example shows how to request additional user details, such as name and picture.
+
+To request the user's name and picture, you need to add the appropriate scopes when authorizing the user in step 1:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=openid%20name%20picture&
+ state=STATE
+```
+
+Now, when you [request tokens](/flows/guides/auth-code/add-login-auth-code#request-tokens), your ID Token will contain the requested name and picture claims. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "name": "jerrie@...",
+ "picture": "https://s.gravatar.com/avatar/6222081fd7dcea7dfb193788d138c457?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fje.png",
+ "iss": "https://auth0pnp.auth0.com/",
+ "sub": "auth0|581...",
+ "aud": "xvt...",
+ "exp": 1478113129,
+ "iat": 1478077129
+}
+```
+
+### Request a User Log In with GitHub
+
+In addition to the usual user authentication, this example shows how to send users directly to a social identity provider, such as GitHub. For this example to work, you will first need to [configure the appropriate connection in the Auth0 Dashboard](${manage_url}/#/connections/social) and get the connection name from the **Settings** tab.
+
+To send users directly to the GitHub login screen, you need to pass the `connection` parameter and set its value to the connection name (in this case, `github`) when authorizing the user in step 1:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=code&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=openid%20name%20picture&
+ state=STATE&
+ connection=github
+```
+
+Now, when you [request tokens](/flows/guides/auth-code/add-login-auth-code#request-tokens), your ID Token will contain a `sub` claim with the user's unique ID returned from GitHub. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "name": "Jerrie Pelser",
+ "nickname": "jerriep",
+ "picture": "https://avatars.githubusercontent.com/u/1006420?v=3",
+ "iss": "https://auth0pnp.auth0.com/",
+ "sub": "github|100...",
+ "aud": "xvt...",
+ "exp": 1478114742,
+ "iat": 1478078742
+}
+```
+
+For a list of possible connections, see [Identity Providers Supported by Auth0](/identityproviders).
diff --git a/articles/flows/guides/auth-code/includes/sample-use-cases-call-api.md b/articles/flows/guides/auth-code/includes/sample-use-cases-call-api.md
new file mode 100644
index 0000000000..3987b1496b
--- /dev/null
+++ b/articles/flows/guides/auth-code/includes/sample-use-cases-call-api.md
@@ -0,0 +1,25 @@
+## Sample Use Cases
+
+### Customize Tokens
+
+You can use [Rules](/rules) to change the returned scopes of Access Tokens and/or add claims to Access and ID Tokens. To do so, add the following rule, which will run after the user authenticates:
+
+```javascript
+function(user, context, callback) {
+
+ // add custom claims to Access Token and ID Token
+ context.accessToken['http://foo/bar'] = 'value';
+ context.idToken['http://fiz/baz'] = 'some other value';
+
+ // change scope
+ context.accessToken.scope = ['array', 'of', 'strings'];
+
+ callback(null, user, context);
+}
+```
+
+Scopes will be available in the token after all rules have run.
+
+::: panel-warning Namespacing Custom Claims
+Auth0 returns profile information in a [structured claim format as defined by the OpenID Connect (OIDC) specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that custom claims added to ID Tokens or Access Tokens must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims.
+:::
diff --git a/articles/flows/guides/client-credentials/call-api-client-credentials.md b/articles/flows/guides/client-credentials/call-api-client-credentials.md
new file mode 100644
index 0000000000..320ac08210
--- /dev/null
+++ b/articles/flows/guides/client-credentials/call-api-client-credentials.md
@@ -0,0 +1,56 @@
+---
+title: Call API Using the Client Credentials Flow
+description: Learn how to call your API from a machine-to-machine (M2M) application using the Client Credentials Flow.
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - client-credentials
+ - M2M
+ - machine-to-machine apps
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
+---
+# Call Your API Using the Client Credentials Flow
+
+::: note
+This tutorial will help you call your API from a machine-to-machine (M2M) application using the Client Credentials Flow. If you want to learn how the flow works and why you should use it, see [Client Credentials Flow](/flows/concepts/client-credentials).
+:::
+
+Auth0 makes it easy for your app to implement the Client Credentials Flow. Following successful authentication, the calling application will have access to an [Access Token](/tokens/concepts/access-tokens), which can be used to call your protected APIs.
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* [Register your API with Auth0](/architecture-scenarios/server-api/part-2#configure-the-api)
+
+* [Register the M2M Application with Auth0](/dashboard/guides/applications/register-app-m2m).
+ * Select an **Application Type** of **Machine to Machine Applications**.
+ * Choose your previously-registered API.
+ * Authorize the M2M Application to call your API.
+
+## Steps
+
+1. [Request a token](#request-token):
+From the authorized application, request an Access Token for your API.
+2. [Call your API](#call-your-api):
+Use the retrieved Access Token to call your API.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+<%= include('./includes/request-token') %>
+
+<%= include('./includes/call-api') %>
+
+<%= include('./includes/sample-use-cases') %>
+
+Once your API receives a request with an Access Token, it will need to validate the token. For details, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+
+## Keep reading
+
+- [How to change scopes and add custom claims to tokens using Hooks](/api-auth/tutorials/client-credentials/customize-with-hooks)
+- [OpenID Connect (OIDC) protocol](/protocols/oidc)
+- [Tokens](/tokens)
diff --git a/articles/flows/guides/client-credentials/includes/call-api.md b/articles/flows/guides/client-credentials/includes/call-api.md
new file mode 100644
index 0000000000..20650469e4
--- /dev/null
+++ b/articles/flows/guides/client-credentials/includes/call-api.md
@@ -0,0 +1,15 @@
+## Call your API
+
+To call your API from the M2M application, the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.
+
+
+ ```har
+{
+ "method": "GET",
+ "url": "https://myapi.com/api",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer ACCESS_TOKEN" }
+ ]
+}
+```
diff --git a/articles/flows/guides/client-credentials/includes/request-token.md b/articles/flows/guides/client-credentials/includes/request-token.md
new file mode 100644
index 0000000000..2e62b59a20
--- /dev/null
+++ b/articles/flows/guides/client-credentials/includes/request-token.md
@@ -0,0 +1,64 @@
+## Request Token
+
+ To access your API, you must request an Access Token for it. To do so, you will need to `POST` to the [token URL](https://auth0.com/docs/api/authentication#client-credentials).
+
+### Example POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "client_credentials"
+ },
+ {
+ "name": "client_id",
+ "value": "YOUR_CLIENT_ID"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "audience",
+ "value": "YOUR_API_IDENTIFIER"
+ }
+ ]
+ }
+}
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "client_credentials". |
+| `client_id` | Your application's Client ID. You can find this value on the [application's settings tab](${manage_url}/#/applications). |
+| `client_secret` | Your application's Client Secret. You can find this value on the [application's settings tab](${manage_url}/#/applications). |
+| `audience` | The audience for the token, which is your API. You can find this in the **Identifier** field on your [API's settings tab](${manage_url}/#/apis). |
+
+
+### Response
+
+ If all goes well, you'll receive an HTTP 200 response with a payload containing `access_token`, `token_type`, and `expires_in` values:
+
+ ```json
+{
+ "access_token":"eyJz93a...k4laUWw",
+ "token_type":"Bearer",
+ "expires_in":86400
+}
+```
+
+
+::: warning
+You should validate your token before saving it. To learn how, see [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
+
diff --git a/articles/flows/guides/client-credentials/includes/sample-use-cases.md b/articles/flows/guides/client-credentials/includes/sample-use-cases.md
new file mode 100644
index 0000000000..a7a969f962
--- /dev/null
+++ b/articles/flows/guides/client-credentials/includes/sample-use-cases.md
@@ -0,0 +1,12 @@
+## Sample Use Cases
+
+### Customize Tokens
+
+You can use [Hooks](/hooks) to change the returned scopes of Access Tokens and/or add claims to them. Auth0 invokes Hooks attached to the client credentials grant at runtime to execute your custom logic.
+
+For more information, see our tutorial on [Using Hooks with the Client Credentials Grant](/api-auth/tutorials/client-credentials/customize-with-hooks).
+
+
+### View Sample Application: Server Client + API
+
+For a sample implementation, see the [Server Client + API](/architecture-scenarios/application/server-api) architecture scenario. This series of tutorials is accompanied by a code sample that you can access in [GitHub](https://github.com/auth0-samples/auth0-pnp-exampleco-timesheets).
diff --git a/articles/flows/guides/device-auth/call-api-device-auth.md b/articles/flows/guides/device-auth/call-api-device-auth.md
new file mode 100644
index 0000000000..b0f3fd4c6b
--- /dev/null
+++ b/articles/flows/guides/device-auth/call-api-device-auth.md
@@ -0,0 +1,20 @@
+---
+title: Call API Using Device Authorization Flow
+description: Learn how to call your API from an input-constrained device using the Device Authorization flow.
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - device-flow
+ - native-apps
+ - desktop-apps
+ - mobile-apps
+ - devices
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
+---
+# Call Your API Using the Device Authorization Flow
+
+<%= include('./includes/index.md') %>
diff --git a/articles/flows/guides/device-auth/includes/call-api.md b/articles/flows/guides/device-auth/includes/call-api.md
new file mode 100644
index 0000000000..20be11679e
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/call-api.md
@@ -0,0 +1,15 @@
+## Call your API
+
+To call your API, the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.
+
+
+ ```har
+{
+ "method": "GET",
+ "url": "https://myapi.com/api",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer ACCESS_TOKEN" }
+ ]
+}
+```
diff --git a/articles/flows/guides/device-auth/includes/index.md b/articles/flows/guides/device-auth/includes/index.md
new file mode 100644
index 0000000000..a7fdf8b8f3
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/index.md
@@ -0,0 +1,66 @@
+::: note
+This tutorial will help you call your own API from an input-constrained device using the Device Authorization Flow. If you want to learn how the flow works and why you should use it, see Device Authorization Flow.
+:::
+
+Auth0 makes it easy for your app to implement the Device Authorization flow using:
+
+* Authentication API: Keep reading to learn how to call our API directly. For an interactive experience, see our Device Flow Playground.
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* Check [limitations](#limitations) to be sure the Device Authorization flow is suitable for your implementation.
+
+* Register the Application with Auth0.
+ * Select an **Application Type** of **Native**.
+ * If necessary, set **Allowed Web Origins**. You can use this to allow localhost as an origin for local development, or to set an allowed origin for specific TV software with architecture subject to CORS (eg: HTML5 + JS). Most applications will not use this setting.
+ * Ensure that the **OIDC Conformant** toggle is enabled. This setting is in the Dashboard under **Application Settings > Advanced > OAuth**.
+ * Make sure the Application's **Grant Types** include **Device Code**. This is also in the Dashboard, under **Application Settings > Advanced > Grant Types**.
+ * If you want your Application to be able to use Refresh Tokens, make sure the Application's **Grant Types** include **Refresh Token**.
+
+* Set up and enable at least one connection for the Application: Database connections, Social connections
+
+* Register your API with Auth0
+ * If you want your API to receive Refresh Tokens to allow it to obtain new tokens when the previous ones expire, enable **Allow Offline Access**.
+
+* Configure Device User Code Settings to define the character set, format, and length of your randomly-generated user code.
+
+## Steps
+
+1. [Request device code](#request-device-code) (Device Flow): Request a device code that the user can use to authorize the device.
+2. [Request device activation](#request-device-activation) (Device Flow): Request that the user authorize the device using their laptop or smartphone.
+3. [Request Tokens](#request-tokens) (Device Flow): Poll the token endpoint to request a token.
+4. [User authorization](#user-authorization) (Browser Flow): The user authorizes the device, so the device can receive tokens.
+5. [Receive Tokens](#receive-tokens) (Device Flow): After the user successfully authorizes the device, receive tokens.
+6. [Call your API](#call-your-api) (Device Flow): Use the retrieved Access Token to call your API.
+7. [Refresh Tokens](#refresh-tokens) (Device Flow): Use a Refresh Token to request new tokens when the existing ones expire.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+Optional: [Troubleshooting](#troubleshooting)
+
+<%= include('./request-device-code') %>
+
+<%= include('./request-device-activation') %>
+
+<%= include('./request-tokens') %>
+
+<%= include('./user-authorization') %>
+
+<%= include('./receive-tokens') %>
+
+<%= include('./call-api') %>
+
+<%= include('./refresh-tokens') %>
+
+<%= include('./sample-use-cases-call-api') %>
+
+<%= include('./troubleshooting') %>
+
+## Keep reading
+
+- The OAuth 2.0 protocol
+- The OpenID Connect protocol
+- Tokens
+- Tenant Logs for Devices
diff --git a/articles/flows/guides/device-auth/includes/receive-tokens.md b/articles/flows/guides/device-auth/includes/receive-tokens.md
new file mode 100644
index 0000000000..a2350b94ad
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/receive-tokens.md
@@ -0,0 +1,29 @@
+
+## Receive Tokens
+
+While the user has been authenticating and authorizing the device, the device app has continued to poll the token URL to request an Access Token.
+
+Once the user has successfully authorized the device, you'll receive an `HTTP 200` response with a payload containing `access_token`, `refresh_token` (optionally), `id_token` (optionally), `token_type`, and `expires_in` values:
+
+```json
+{
+ "access_token":"eyJz93a...k4laUWw",
+ "refresh_token":"GEbRxBN...edjnXbL",
+ "id_token": "eyJ0XAi...4faeEoQ",
+ "token_type":"Bearer",
+ "expires_in":86400
+}
+```
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate Access Tokens](/tokens/guides/validate-access-tokens) and [Validate ID Tokens](/tokens/guides/validate-id-tokens).
+:::
+
+[Access Tokens](/tokens/concepts/access-token) are used to call the [Auth0 Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or another API. You will be able to use the Access Token to call `/userinfo` only if you included the `openid` scope. If you are calling your own API, the first thing your API will need to do is [verify the Access Token](/tokens/guides/validate-access-tokens).
+
+[ID Tokens](/tokens/concepts/id-tokens) contain user information that must be [decoded and extracted](/tokens/id-tokens#id-token-payload). The `id_token` will only be present in the response if you included the `openid` scope.
+
+[Refresh Tokens](/tokens/concepts/refresh-tokens) are used to obtain a new Access Token or ID Token after the previous one has expired. The `refresh_token` will only be present in the response if you included the `offline_access` scope and enabled __Allow Offline Access__ for your API in the Dashboard.
+
+::: warning
+Refresh Tokens must be stored securely since they allow a user to remain authenticated essentially forever.
+:::
diff --git a/articles/flows/guides/device-auth/includes/refresh-tokens.md b/articles/flows/guides/device-auth/includes/refresh-tokens.md
new file mode 100644
index 0000000000..9bea311641
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/refresh-tokens.md
@@ -0,0 +1,71 @@
+## Refresh Tokens
+
+You have already received a [Refresh Token](/tokens/concepts/refresh-tokens) if you've been following this tutorial and completed the following:
+
+* configured your API to allow offline access
+* included the `offline_access` scope when you initiated the authentication request through the [authorize](/api/authentication/reference#authorize-application) endpoint
+
+You can use the Refresh Token to get a new Access Token. Usually, a user will need a new Access Token only after the previous one expires or when gaining access to a new resource for the first time. It's bad practice to call the endpoint to get a new Access Token every time you call an API, and Auth0 maintains rate limits that will throttle the amount of requests to the endpoint that can be executed using the same token from the same IP.
+
+To refresh your token, make a `POST` request to the `/oauth/token` endpoint in the Authentication API, using `grant_type=refresh_token`.
+
+### Example refresh token POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params" : [
+ {
+ "name": "grant_type",
+ "value": "refresh_token"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "${account.clientSecret}"
+ },
+ {
+ "name": "refresh_token",
+ "value": "YOUR_REFRESH_TOKEN"
+ }
+ ]
+ }
+}
+```
+
+#### Refresh Token Request Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "refresh_token". |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `client_secret` | Your application's Client Secret. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientSecret}/settings). |
+| `refresh_token` | The Refresh Token to use. |
+| `scope` | (Optional) A space-delimited list of requested scope permissions. If not sent, the original scopes will be used; otherwise you can request a reduced set of scopes. Note that this must be URL encoded. |
+
+### Refresh Token Response
+
+If all goes well, you'll receive an `HTTP 200` response with a payload containing a new `access_token`, `id_token` (optionally), token lifetime in seconds (`expires_in`), granted `scope` values, and `token_type`:
+
+```json
+{
+ "access_token": "eyJ...MoQ",
+ "expires_in": 86400,
+ "scope": "openid offline_access",
+ "id_token": "eyJ...0NE",
+ "token_type": "Bearer"
+}
+```
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate Access Tokens](/tokens/guides/validate-access-tokens) and [Validate ID Tokens](/tokens/guides/validate-id-tokens).
+:::
diff --git a/articles/flows/guides/device-auth/includes/request-device-activation.md b/articles/flows/guides/device-auth/includes/request-device-activation.md
new file mode 100644
index 0000000000..b6429b9025
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/request-device-activation.md
@@ -0,0 +1,11 @@
+## Request Device Activation
+
+Once you have received a `device_code` and `user_code`, you must ask the user to go to the `verification_uri` on their laptop or smartphone and enter the `user_code`:
+
+
+
+The `device_code` is not intended for the user directly and should not be displayed during the interaction to avoid confusing the user.
+
+::: note
+When building a CLI, you could skip this step and immediately open the browser with `verification_uri_complete`.
+:::
diff --git a/articles/flows/guides/device-auth/includes/request-device-code.md b/articles/flows/guides/device-auth/includes/request-device-code.md
new file mode 100644
index 0000000000..4aca46bb7a
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/request-device-code.md
@@ -0,0 +1,89 @@
+## Request Device Code
+
+Once the user has started their device app and wants to authorize the device, you'll need to get a device code. When the user begins their session in their browser-based device, this code will be bound to that session.
+
+To get the device code, your app must request a code from the [device code URL](/api/authentication#get-device-code), including the Client ID.
+
+### Example POST to device code URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/device/code",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params" : [
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "scope",
+ "value": "SCOPE"
+ },
+ {
+ "name": "audience",
+ "value": "AUDIENCE"
+ }
+ ]
+ }
+}
+```
+
+#### Device Code Parameters
+
+Note that when requesting a device code to call a custom API, you:
+
+- must include an audience parameter
+- can include additional scopes supported by the target API
+
+::: note
+ If your app wants an Access Token only to retrieve info about the authenticated user, then no audience parameter is required.
+:::
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `client_id` |Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `scope` | The [scopes](/scopes) for which you want to request authorization. These must be separated by a space. You can request any of the [standard OIDC scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, [custom claims](/tokens/concepts/jwt-claims#custom-claims) conforming to a [namespaced format](/tokens/guides/create-namespaced-custom-claims), or any [scopes supported by the target API](/scopes/current/api-scopes) (e.g., `read:contacts`). Include `openid` to get an ID Token or to be able to use the [/userinfo endpoint](/api/authentication#user-profile) to retrieve profile information for the user. Include `offline_access` to get a Refresh Token (make sure that the __Allow Offline Access__ field is enabled in the [API Settings](${manage_url}/#/apis)). Note that this must be URL encoded. |
+|`audience` | The unique identifier of the API your app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial. Note that this must be URL encoded. |
+
+### Device Code Response
+
+If all goes well, you'll receive an HTTP 200 response with a payload containing `device_code`, `user_code`, `verification_uri`, and `expires_in`, `interval`, and `verification_uri_complete` values:
+
+```json
+{
+ "device_code": "Ag_EE...ko1p",
+ "user_code": "QTZL-MCBW",
+ "verification_uri": "https://accounts.acmetest.org/activate",
+ "verification_uri_complete": "https://accounts.acmetest.org/activate?user_code=QTZL-MCBW",
+ "expires_in": 900,
+ "interval": 5
+}
+```
+
+* `device_code` is the unique code for the device. When the user goes to the `verification_uri` in their browser-based device, this code will be bound to their session.
+* `user_code` contains the code that should be input at the `verification_uri` to authorize the device.
+* `verification_uri` contains the URL the user should visit to authorize the device.
+* `verification_uri_complete` contains the complete URL the user should visit to authorize the device. This allows your app to embed the `user_code` in the URL, if you so choose.
+* `expires_in` indicates the lifetime (in seconds) of the `device_code` and `user_code`.
+* `interval` indicates the interval (in seconds) at which the app should poll the token URL to request a token.
+
+::: note
+You can [configure the character set, format, and length of your randomly-generated user code](/dashboard/guides/tenants/configure-device-user-code-settings) in your tenant settings.
+
+To prevent brute force attacks, we enforce the following limits on `user_code`:
+
+**Minimum length**:
+* BASE20 Letters: 8 characters
+* Numbers: 9 characters
+
+**Maximum length**:
+* 20 characters (including hyphens and spaces, which may be added as separators for readability)
+
+**Expiration time**:
+* 15 minutes
+:::
diff --git a/articles/flows/guides/device-auth/includes/request-tokens.md b/articles/flows/guides/device-auth/includes/request-tokens.md
new file mode 100644
index 0000000000..d2b1de6a53
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/request-tokens.md
@@ -0,0 +1,107 @@
+## Request Tokens
+
+While you are waiting for the user to activate the device, begin polling the token URL to request an Access Token. Using the extracted polling interval (`interval`) from the previous step, you will need to `POST` to the [token URL](/api/authentication#device-auth) sending along the `device_code`.
+
+To avoid errors due to network latency, you should start counting each interval after receipt of the last polling request's response.
+
+### Example request token POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "urn:ietf:params:oauth:grant-type:device_code"
+ },
+ {
+ "name": "device_code",
+ "value": "YOUR_DEVICE_CODE"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ }
+ ]
+ }
+}
+```
+
+#### Token Request Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "urn:ietf:params:oauth:grant-type:device_code". This is an extension grant type (as defined by Section 4.5 of [RFC6749](https://tools.ietf.org/html/rfc6749#section-4.5)). Note that this must be URL encoded. |
+| `device_code` | The `device_code` retrieved in the previous step of this tutorial. |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+
+### Token Responses
+
+While you wait for the user to authorize the device, you may receive a few different `HTTP 4xx` responses:
+
+#### Authorization pending
+
+You will see this error while waiting for the user to take action. Continue polling using the suggested interval retrieved in the previous step of this tutorial.
+
+```json
+`HTTP 403`
+
+{
+ "error": "authorization_pending",
+ "error_description": "..."
+}
+```
+
+#### Slow down
+
+You are polling too fast. Slow down and use the suggested interval retrieved in the previous step of this tutorial. To avoid receiving this error due to network latency, you should start counting each interval after receipt of the last polling request's response.
+
+```json
+`HTTP 429`
+
+{
+ "error": "slow_down",
+ "error_description": "..."
+}
+```
+
+#### Expired Token
+
+The user has not authorized the device quickly enough, so the `device_code` has expired. Your application should notify the user that the flow has expired and prompt them to reinitiate the flow.
+
+::: note
+Then `expired_token` error will be returned exactly once; after that, the dreaded `invalid_grant` will be returned. Your device *must* stop polling.
+:::
+
+```json
+`HTTP 403`
+
+{
+ "error": "expired_token",
+ "error_description": "..."
+}
+```
+
+#### Access Denied
+
+Finally, if access is denied, you will receive:
+
+```json
+`HTTP 403`
+
+{
+ "error": "access_denied",
+ "error_description": "..."
+}
+```
+This can occur for a variety of reasons, including:
+
+* the user refused to authorize the device
+* the authorization server denied the transaction
+* a configured [Rule](/rules) denied access
diff --git a/articles/flows/guides/device-auth/includes/sample-use-cases-call-api.md b/articles/flows/guides/device-auth/includes/sample-use-cases-call-api.md
new file mode 100644
index 0000000000..8b5955b216
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/sample-use-cases-call-api.md
@@ -0,0 +1,21 @@
+## Sample Use Cases
+
+### Detect Device Authorization Flow Use
+
+You can use [Rules](/rules) to detect whether the current transaction is using the Device Authorization Flow. To do so, check the `context` object's `protocol` property:
+
+```javascript
+function (user, context, callback) {
+ if (context.protocol === 'oauth2-device-code') {
+ ...
+ }
+
+ callback(null, user, context);
+}
+```
+
+### Sample Implementations
+
+* [Device Authorization Playground](https://auth0.github.io/device-flow-playground/)
+* [AppleTV (Swift)](https://github.com/pushpabrol/auth0-device-flow-appletv): Simple application that shows how Auth0 can be used with the Device Authorization Flow from an AppleTV.
+* [CLI (Node.js)](https://gist.github.com/panva/652c61e7d847e0ed99926c324fa91b36): Sample implementation of a CLI that uses the Device Authorization Flow instead of the Authorization Code Flow. The major difference is that your CLI does not need to host a webserver and listen on a port.
\ No newline at end of file
diff --git a/articles/flows/guides/device-auth/includes/troubleshooting.md b/articles/flows/guides/device-auth/includes/troubleshooting.md
new file mode 100644
index 0000000000..7815d9016d
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/troubleshooting.md
@@ -0,0 +1,29 @@
+# Troubleshooting
+
+[Tenant logs](/logs) are created for any interaction that takes place and can be used to troubleshoot issues.
+
+## Error codes
+
+| Code | Name | Description |
+|------------|------|-------------|
+| `fdeaz` | Failed device authorization request | |
+| `fdeac` | Failed device activation | |
+| `fdecc` | User canceled the device confirmation | |
+| `fede` | Failed Exchange | Device Code for Access Token |
+| `sede` | Success Exchange | Device Code for Access Token |
+
+## Limitations
+
+To use the Device Authorization Flow, devices must:
+
+* Support Server Name Indication (SNI)
+* Have an [Auth0 application type](/applications) of **Native**
+* Have the [**Token Endpoint Authentication Method**](/dashboard/reference/settings-application) set to **None**
+* Be [OIDC-conformant](/dashboard/reference/settings-application#oauth)
+* Not be created through [Dynamic Client Registration](/api-auth/dynamic-client-registration)
+
+In addition, the Device Authorization Flow does not allow:
+* [Social Connections](/connections) using [Auth0 developer keys](/connections/social/devkeys) unless you are using new [New Universal Login Experience](/universal-login/new).
+* Query string parameters to be accessed from hosted login page or rules
+
+We support the full [Draft 15](https://tools.ietf.org/html/draft-ietf-oauth-device-flow-15), except for confidential Clients.
diff --git a/articles/flows/guides/device-auth/includes/user-authorization.md b/articles/flows/guides/device-auth/includes/user-authorization.md
new file mode 100644
index 0000000000..360a4bb7cf
--- /dev/null
+++ b/articles/flows/guides/device-auth/includes/user-authorization.md
@@ -0,0 +1,24 @@
+## User Authorization
+
+The user will either scan the QR code, or else will open the activation page and enter the user code:
+
+
+
+A confirmation page will be shown to have the user confirm that this is the right device:
+
+
+
+The user will complete the transaction by signing in. This step may include one or more of the following processes:
+
+* Authenticating the user;
+* Redirecting the user to an Identity Provider to handle authentication;
+* Checking for active SSO sessions;
+* Obtaining user consent for the device, unless consent has been previously given.
+
+
+
+Upon successful authentication and consent, the confirmation prompt will be shown:
+
+
+
+At this point, the user has authenticated, and the device has been authorized.
\ No newline at end of file
diff --git a/articles/flows/guides/implicit/add-login-implicit.md b/articles/flows/guides/implicit/add-login-implicit.md
new file mode 100644
index 0000000000..36373a31b2
--- /dev/null
+++ b/articles/flows/guides/implicit/add-login-implicit.md
@@ -0,0 +1,54 @@
+---
+title: Add Login Using the Implicit Flow with Form Post
+description: Learn how to add login to your single-page application (SPA) using the Implicit Flow with Form Post.
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - hybrid-flow
+ - implicit-flow
+ - SPA
+ - single-page apps
+contentType: tutorial
+useCase:
+ - add-login
+---
+# Add Login Using the Implicit Flow with Form Post
+
+::: note
+This tutorial will help you add login to your single-page application (SPA) using the Implicit Flow with Form Post. If you want to learn how the flow works and why you should use it, see [Implicit Flow with Form Post](/flows/concepts/implicit).
+
+You can use the Implicit Flow with Form Post for login-only use cases; if you need to request Access Tokens while logging the user in so you can call your API, use the [Authorization Code Flow with PKCE](/flows/concepts/auth-code-pkce).
+:::
+
+Auth0 makes it easy to implement the Implicit Flow with Form Post by using:
+
+* [Express OpenID Connect SDK](https://www.npmjs.com/package/express-openid-connect): The easiest way to implement the flow, which will do most of the heavy-lifting for you. If you use our [Javascript SDK](/libraries/auth0js), please ensure you are implementing mitigations that are appropriate for your architecture.
+* Authentication API: If you prefer to roll your own solution, keep reading to learn how to call our API directly.
+
+Following successful login, your application will have access to the user's [ID Token](/tokens/id-tokens). The ID Token will contain basic user profile information.
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* [Register your Application with Auth0](applications/spa)
+ * Select an **Application Type** of **Single-Page App**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Implicit**.
+
+## Steps
+
+1. [Authorize the user](#authorize-the-user): Request the user's authorization and redirect back to your app.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+<%= include('./includes/authorize-user-add-login') %>
+
+<%= include('./includes/sample-use-cases-add-login') %>
+
+## Keep reading
+
+- [The OAuth 2.0 protocol](/protocols/oauth2)
+- [OpenID Connect (OIDC) protocol](/protocols/oidc)
+- [Tokens](/tokens)
diff --git a/articles/flows/guides/implicit/call-api-implicit.md b/articles/flows/guides/implicit/call-api-implicit.md
new file mode 100644
index 0000000000..c524badcde
--- /dev/null
+++ b/articles/flows/guides/implicit/call-api-implicit.md
@@ -0,0 +1,57 @@
+---
+title: Call API Using the Implicit Flow
+description: Learn how to call your API from single-page apps (SPA) using the Implicit Flow.
+toc: true
+topics:
+ - api-authentication
+ - oidc
+ - implicit-flow
+ - single-page apps
+ - SPA
+contentType: tutorial
+useCase:
+ - secure-api
+ - call-api
+---
+# Call Your API Using the Implicit Flow
+
+::: note
+This tutorial will help you call your own API from a single-page application (SPA) using the Implicit Flow. If you want to learn how the flow works and why you should use it, see [Implicit Flow](/flows/concepts/implicit). If you want to learn to add login to your single-page application (SPA), see [Add Login Using the Implicit Flow](/flows/guides/implicit/add-login-implicit).
+:::
+
+Auth0 makes it easy for your app to implement the Implicit Flow using:
+
+* [Auth0.js](/libraries/auth0js): The easiest way to implement the flow, which will do most of the heavy-lifting for you. Our [Single-Page App Quickstarts](/quickstart/spa) will walk you through the process.
+* Authentication API: If you prefer to roll your own, keep reading to learn how to call our API directly.
+
+## Prerequisites
+
+**Before beginning this tutorial:**
+
+* [Register your Application with Auth0](/dashboard/guides/applications/register-app-spa).
+ * Select an **Application Type** of **Single-Page App**.
+ * Add an **Allowed Callback URL** of **`${account.callback}`**.
+ * Make sure your Application's **[Grant Types](/dashboard/guides/applications/update-grant-types)** include **Implicit**.
+
+* [Register your API with Auth0](/architecture-scenarios/spa-api/part-2#create-the-api)
+
+## Steps
+
+1. [Authorize the user](#authorize-the-user):
+Request the user's authorization and redirect back to your app with the requested credentials.
+2. [Call Your API](#call-your-api):
+Use the retrieved Access Token to call your API.
+
+Optional: [Explore Sample Use Cases](#sample-use-cases)
+
+<%= include('./includes/authorize-user-call-api') %>
+
+<%= include('./includes/call-api') %>
+
+<%= include('./includes/sample-use-cases-call-api') %>
+
+## Keep reading
+
+- [OAuth 2.0 framework](/protocols/oauth2)
+- [OpenID Connect (OIDC) protocol](/protocols/oidc)
+- [Tokens](/tokens)
diff --git a/articles/flows/guides/implicit/includes/authorize-user-add-login.md b/articles/flows/guides/implicit/includes/authorize-user-add-login.md
new file mode 100644
index 0000000000..8f057fee2e
--- /dev/null
+++ b/articles/flows/guides/implicit/includes/authorize-user-add-login.md
@@ -0,0 +1,80 @@
+## Authorize the user
+
+To begin the flow, you'll need to get the user's authorization. This step may include one or more of the following processes:
+
+* Authenticating the user;
+* Redirecting the user to an Identity Provider to handle authentication;
+* Checking for active Single Sign-on (SSO) sessions;
+* Obtaining user consent for the requested permission level, unless consent has been previously given.
+
+To authorize the user, your app must send the user to the authorization URL.
+
+### Example authorization URL
+
+```text
+https://${account.namespace}/authorize?
+ response_type=YOUR_RESPONSE_TYPE&
+ response_mode=form_post&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ state=STATE&
+ nonce=NONCE
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+| -------------- | ----------- |
+| `response_type` | Denotes the kind of credential that Auth0 will return (code or token). For the Implicit Flow, the value can be `id_token`, `token`, or `id_token token`. Specifically, `id_token` returns an ID Token, and `token` returns an Access Token. |
+| `response_mode` | Specifies the method with which response parameters should be returned. For security purposes, the value should be `form_post`. In this mode, response parameters will be encoded as HTML form values that are transmitted via the HTTP POST method and encoded in the body using the `application/x-www-form-urlencoded` format. |
+| `client_id` | Your application's Client ID. You can find this value at your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings). |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. You must specify this URL as a valid callback URL in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings).
**Warning:** Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments. |
+| `scope` | Specifies the [scopes](/scopes) for which you want to request authorization, which dictate which claims (or user attributes) you want returned. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, [custom claims](/tokens/concepts/jwt-claims#custom-claims) conforming to a [namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). |
+| `state` | (recommended) An opaque arbitrary alphanumeric string that your app adds to the initial request and Auth0 includes when redirecting back to your application. To see how to use this value to prevent cross-site request forgery (CSRF) attacks, see [Mitigate CSRF Attacks With State Parameters](/protocols/oauth2/mitigate-csrf-attacks). |
+| `nonce` | (required for `response_type` containing `id_token token`, otherwise recommended) A cryptographically random string that your app adds to the initial request and Auth0 includes inside the ID Token, [used to prevent token replay attacks](/api-auth/tutorials/nonce). |
+| `connection` | (optional) Forces the user to sign in with a specific connection. For example, you can pass a value of `github` to send the user directly to GitHub to log in with their GitHub account. When not specified, the user sees the Auth0 Lock screen with all configured connections. You can see a list of your configured connections on the **Connections** tab of your application. |
+
+As an example, your HTML snippet for your authorization URL when adding login to your app might look like:
+
+```html
+
+ Sign In
+
+```
+
+### Response
+
+If all goes well, you'll receive an `HTTP 302` response. The requested credentials are encoded in the body:
+
+```text
+HTTP/1.1 302 Found
+Content-Type: application/x-www-form-urlencoded
+
+id_token=eyJ...acA&
+state=xyzABC123
+```
+
+Note that the returned values depend on what you requested as a `response_type`.
+
+| Response Type | Components |
+| ------------------- | ---------- |
+| id_token | ID Token |
+| token | Access Token (plus `expires_in` and `token_type` values) |
+| id_token token | ID Token, Access Token (plus `expires_in` and `token_type` values) |
+
+Auth0 will also return any state value you included in your call to the authorization URL.
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Tokens](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
+
+[ID Tokens](/tokens/concepts/id-tokens) contain user information that must be [decoded and extracted](/tokens/concepts/id-tokens#id-token-payload).
+
+[Access Tokens](/tokens/concepts/access-tokens) are used to call the [Auth0 Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or another API. If you are calling your own API, the first thing your API will need to do is [verify the Access Token](/tokens/guides/validate-access-tokens).
\ No newline at end of file
diff --git a/articles/flows/guides/implicit/includes/authorize-user-call-api.md b/articles/flows/guides/implicit/includes/authorize-user-call-api.md
new file mode 100644
index 0000000000..08d668c77e
--- /dev/null
+++ b/articles/flows/guides/implicit/includes/authorize-user-call-api.md
@@ -0,0 +1,78 @@
+## Authorize the user
+
+To begin the flow, you'll need to get the user's authorization. This step may include one or more of the following processes:
+
+* Authenticating the user;
+* Redirecting the user to an Identity Provider to handle authentication;
+* Checking for active Single Sign-on (SSO) sessions;
+* Obtaining user consent for the requested permission level, unless consent has been previously given.
+
+To authorize the user, your app must send the user to the authorization URL.
+
+### Example authorization URL
+
+```text
+https://${account.namespace}/authorize?
+ response_type=YOUR_RESPONSE_TYPE&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=YOUR_SCOPE&
+ audience=YOUR_API_AUDIENCE&
+ state=STATE&
+ nonce=NONCE
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+| -------------- | ----------- |
+| `response_type` | Denotes the kind of credential that Auth0 will return (code or token). For the Implicit Flow, the value can be `id_token`, `token`, or `id_token token`. Specifically, `id_token` returns an ID Token, and `token` returns an Access Token. |
+| `client_id` | Your application's Client ID. You can find this value at your [Application's Settings](${manage_url}/#/applications/${account.clientId}/settings). |
+| `redirect_uri` | The URL to which Auth0 will redirect the browser after authorization has been granted by the user. You must specify this URL as a valid callback URL in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings).
**Warning:** Per the [OAuth 2.0 Specification](https://tools.ietf.org/html/rfc6749#section-3.1.2), Auth0 removes everything after the hash and does *not* honor any fragments. |
+| `scope` | Specifies the [scopes](/scopes) for which you want to request authorization, which dictate which claims (or user attributes) you want returned. These must be separated by a space. You can request any of the [standard OpenID Connect (OIDC) scopes](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) about users, such as `profile` and `email`, [custom claims](/tokens/concepts/jwt-claims#custom-claims) conforming to a [namespaced format](/tokens/guides/create-namespaced-custom-claims), or any scopes supported by the target API (for example, `read:contacts`). |
+| `audience` | The unique identifier of the API the web app wants to access. Use the **Identifier** value on the [Settings](${manage_url}/#/apis) tab for the API you created as part of the prerequisites for this tutorial. |
+| `state` | (recommended) An opaque arbitrary alphanumeric string that your app adds to the initial request and Auth0 includes when redirecting back to your application. To see how to use this value to prevent cross-site request forgery (CSRF) attacks, see [Mitigate CSRF Attacks With State Parameters](/protocols/oauth2/mitigate-csrf-attacks). |
+| `nonce` | (required for `response_type` containing `id_token token`, otherwise recommended) A cryptographically random string that your app adds to the initial request and Auth0 includes inside the ID Token, [used to prevent token replay attacks](/api-auth/tutorials/nonce). |
+
+As an example, your HTML snippet for your authorization URL when adding login to your app might look like:
+
+```html
+
+ Sign In
+
+```
+
+
+### Response
+
+If all goes well, you'll receive an `HTTP 302` response. The requested credentials are included in a hash fragment at the end of the URL:
+
+```text
+HTTP/1.1 302 Found
+Location: ${account.callback}#access_token=ey...MhPw&expires_in=7200&token_type=Bearer&id_token=ey...Fyqk&state=xyzABC123
+```
+
+Note that the returned values depend on what you requested as a `response_type`.
+
+| Response Type | Components |
+| ------------------- | ---------- |
+| id_token | ID Token |
+| token | Access Token (plus `expires_in` and `token_type` values) |
+| id_token token | ID Token, Access Token (plus `expires_in` and `token_type` values) |
+
+Auth0 will also return any state value you included in your call to the authorization URL.
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Tokens](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
+
+[ID Tokens](/tokens/concepts/id-tokens) contain user information that must be [decoded and extracted](/tokens/concepts/id-tokens#id-token-payload).
+
+[Access Tokens](/tokens/concepts/access-tokens) are used to call the [Auth0 Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or another API. If you are calling your own API, the first thing your API will need to do is [verify the Access Token](/tokens/guides/validate-access-tokens).
diff --git a/articles/flows/guides/implicit/includes/call-api.md b/articles/flows/guides/implicit/includes/call-api.md
new file mode 100644
index 0000000000..61d453a2c1
--- /dev/null
+++ b/articles/flows/guides/implicit/includes/call-api.md
@@ -0,0 +1,15 @@
+## Call your API
+
+To call your API from a SPA, the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.
+
+
+ ```har
+{
+ "method": "GET",
+ "url": "https://myapi.com/api",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer ACCESS_TOKEN" }
+ ]
+}
+```
diff --git a/articles/flows/guides/implicit/includes/refresh-tokens.md b/articles/flows/guides/implicit/includes/refresh-tokens.md
new file mode 100644
index 0000000000..4ebc667073
--- /dev/null
+++ b/articles/flows/guides/implicit/includes/refresh-tokens.md
@@ -0,0 +1,66 @@
+## Refresh Tokens
+
+You have already received a Refresh Token if you've been following this tutorial and completed the following:
+
+* configured your API to allow offline access
+* included the `offline_access` scope when you initiated the authentication request through the [authorize](/api/authentication/reference#authorize-application) endpoint
+
+You can use the Refresh Token to get a new Access Token. Usually, a user will need a new Access Token only after the previous one expires or when gaining access to a new resource for the first time. It's bad practice to call the endpoint to get a new Access Token every time you call an API, and Auth0 maintains rate limits that will throttle the amount of requests to the endpoint that can be executed using the same token from the same IP.
+
+To refresh your token, make a `POST` request to the `/oauth/token` endpoint in the Authentication API, using `grant_type=refresh_token`.
+
+### Example POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "refresh_token"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "refresh_token",
+ "value": "YOUR_REFRESH_TOKEN"
+ }
+ ]
+ }
+}
+```
+
+#### Parameters
+
+| Parameter Name | Description |
+|-----------------|-------------|
+| `grant_type` | Set this to "refresh_token". |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `refresh_token` | The Refresh Token to use. |
+| `scope` | (optional) A space-delimited list of requested scope permissions. If not sent, the original scopes will be used; otherwise you can request a reduced set of scopes. Note that this must be URL encoded. |
+
+### Response
+
+If all goes well, you'll receive an `HTTP 200` response with a payload containing a new `access_token`, its lifetime in seconds (`expires_in`), granted `scope` values, and `token_type`. If the scope of the initial token included `openid`, then the response will also include a new `id_token`:
+
+```json
+{
+ "access_token": "eyJ...MoQ",
+ "expires_in": 86400,
+ "scope": "openid offline_access",
+ "id_token": "eyJ...0NE",
+ "token_type": "Bearer"
+}
+```
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Tokens](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
diff --git a/articles/flows/guides/implicit/includes/request-tokens.md b/articles/flows/guides/implicit/includes/request-tokens.md
new file mode 100644
index 0000000000..406e1564ad
--- /dev/null
+++ b/articles/flows/guides/implicit/includes/request-tokens.md
@@ -0,0 +1,78 @@
+## Request Tokens
+
+Now that you have an authorization code, you can exchange it for tokens. The Access Token you receive will allow you to call the API specified when you authorized the user. Using the extracted Authorization Code (`code`) from the first step, you will need to `POST` to the [Token URL](/api/authentication?http#authorization-code).
+
+### Example POST to token URL
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/oauth/token",
+ "headers": [
+ { "name": "Content-Type", "value": "application/x-www-form-urlencoded" }
+ ],
+ "postData" : {
+ "mimeType": "application/x-www-form-urlencoded",
+ "params": [
+ {
+ "name": "grant_type",
+ "value": "authorization_code"
+ },
+ {
+ "name": "code",
+ "value": "YOUR_AUTHORIZATION_CODE"
+ },
+ {
+ "name": "client_id",
+ "value": "${account.clientId}"
+ },
+ {
+ "name": "client_secret",
+ "value": "YOUR_CLIENT_SECRET"
+ },
+ {
+ "name": "redirect_uri",
+ "value": "${account.callback}"
+ }
+ ]
+ }
+}
+```
+
+#### Parameters
+
+| Parameter | Description |
+| --------- | ----------- |
+| `grant_type` | Set this to "authorization_code". |
+| `code` | The `authorization_code` retrieved in the previous step of this tutorial. |
+| `client_id` | Your application's Client ID. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `client_secret` | Your application's Client Secret. You can find this value in your [Application Settings](${manage_url}/#/Applications/${account.clientId}/settings). |
+| `redirect_uri` | The valid callback URL set in your Application settings. This must exactly match the `redirect_uri` passed to the authorization URL in the previous step of this tutorial. Note that this must be URL encoded. |
+
+
+### Response
+
+If all goes well, you'll receive an HTTP 200 response with a payload containing `access_token`, `refresh_token`, `id_token`, and `token_type` values:
+
+```js
+{
+ "access_token": "eyJz93a...k4laUWw",
+ "refresh_token": "GEbRxBN...edjnXbL",
+ "id_token": "eyJ0XAi...4faeEoQ",
+ "token_type": "Bearer"
+}
+```
+
+::: warning
+You should validate your tokens before saving them. To learn how, see [Validate ID Tokens](/tokens/guides/validate-id-tokens) and [Validate Access Tokens](/tokens/guides/validate-access-tokens).
+:::
+
+[ID Tokens](/tokens/concepts/id-tokens) contain user information that must be [decoded and extracted](/tokens/concepts/id-tokens#id-token-payload).
+
+[Access Tokens](/tokens/concepts/access-token) are used to call the [Auth0 Authentication API's `/userinfo` endpoint](/api/authentication#get-user-info) or another API. If you are calling your own API, the first thing your API will need to do is [verify the Access Token](/tokens/guides/validate-access-tokens).
+
+[Refresh Tokens](/tokens/concepts/refresh-tokens) are used to obtain a new Access Token or ID Token after the previous one has expired. The `refresh_token` will only be present in the response if you included the `offline_access` scope and enabled __Allow Offline Access__ for your API in the Dashboard.
+
+::: warning
+Refresh Tokens must be stored securely since they allow a user to remain authenticated essentially forever.
+:::
diff --git a/articles/flows/guides/implicit/includes/sample-use-cases-add-login.md b/articles/flows/guides/implicit/includes/sample-use-cases-add-login.md
new file mode 100644
index 0000000000..410a8637a1
--- /dev/null
+++ b/articles/flows/guides/implicit/includes/sample-use-cases-add-login.md
@@ -0,0 +1,83 @@
+## Sample Use Cases
+
+### Basic Authentication Request
+
+This example shows the most basic request you can make when authorizing the user in step 1. It displays the Auth0 login screen and allows the user to sign in with any of your configured connections:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=id_token&
+ response_mode=form_post&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ nonce=NONCE
+```
+
+This will return an ID Token, which you can parse from your redirect URL.
+
+
+### Request the User's Name and Profile Picture
+
+In addition to the usual user authentication, this example shows how to request additional user details, such as name and picture.
+
+To request the user's name and picture, you need to add the appropriate scopes when authorizing the user in step 1:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=id_token token&
+ response_mode=form_post&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=openid%20name%20picture&
+ state=STATE&
+ nonce=NONCE
+```
+
+Now, your ID Token will contain the requested name and picture claims. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "name": "jerrie@...",
+ "picture": "https://s.gravatar.com/avatar/6222081fd7dcea7dfb193788d138c457?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fje.png",
+ "iss": "https://auth0pnp.auth0.com/",
+ "sub": "auth0|581...",
+ "aud": "xvt...",
+ "exp": 1478113129,
+ "iat": 1478077129
+}
+```
+
+### Request a User Log In with GitHub
+
+In addition to the usual user authentication, this example shows how to send users directly to a social identity provider, such as GitHub. For this example to work, you will first need to [configure the appropriate connection in the Auth0 Dashboard](${manage_url}/#/connections/social) and get the connection name from the **Settings** tab.
+
+To send users directly to the GitHub login screen, you need to pass the `connection` parameter and set its value to the connection name (in this case, `github`) when authorizing the user in step 1:
+
+```text
+https://${account.namespace}/authorize?
+ response_type=id_token token&
+ response_mode=form_post&
+ client_id=${account.clientId}&
+ redirect_uri=${account.callback}&
+ scope=openid%20name%20picture&
+ state=STATE&
+ nonce=NONCE&
+ connection=github
+```
+
+Now, your ID Token will contain a `sub` claim with the user's unique ID returned from GitHub. When you [decode the ID Token](/tokens/id-tokens#id-token-payload), it will look similar to:
+
+```json
+{
+ "name": "Jerrie Pelser",
+ "nickname": "jerriep",
+ "picture": "https://avatars.githubusercontent.com/u/1006420?v=3",
+ "iss": "https://auth0pnp.auth0.com/",
+ "sub": "github|100...",
+ "aud": "xvt...",
+ "exp": 1478114742,
+ "iat": 1478078742
+}
+```
+
+For a list of possible connections, see [Identity Providers Supported by Auth0](/identityproviders).
diff --git a/articles/flows/guides/implicit/includes/sample-use-cases-call-api.md b/articles/flows/guides/implicit/includes/sample-use-cases-call-api.md
new file mode 100644
index 0000000000..3987b1496b
--- /dev/null
+++ b/articles/flows/guides/implicit/includes/sample-use-cases-call-api.md
@@ -0,0 +1,25 @@
+## Sample Use Cases
+
+### Customize Tokens
+
+You can use [Rules](/rules) to change the returned scopes of Access Tokens and/or add claims to Access and ID Tokens. To do so, add the following rule, which will run after the user authenticates:
+
+```javascript
+function(user, context, callback) {
+
+ // add custom claims to Access Token and ID Token
+ context.accessToken['http://foo/bar'] = 'value';
+ context.idToken['http://fiz/baz'] = 'some other value';
+
+ // change scope
+ context.accessToken.scope = ['array', 'of', 'strings'];
+
+ callback(null, user, context);
+}
+```
+
+Scopes will be available in the token after all rules have run.
+
+::: panel-warning Namespacing Custom Claims
+Auth0 returns profile information in a [structured claim format as defined by the OpenID Connect (OIDC) specification](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). This means that custom claims added to ID Tokens or Access Tokens must [conform to a namespaced format](/tokens/guides/create-namespaced-custom-claims) to avoid possible collisions with standard OIDC claims.
+:::
diff --git a/articles/flows/index.md b/articles/flows/index.md
new file mode 100644
index 0000000000..424e69d796
--- /dev/null
+++ b/articles/flows/index.md
@@ -0,0 +1,90 @@
+---
+url: /flows
+section: articles
+classes: topic-page
+title: Authentication and Authorization Flows
+description: Introduction to the various flows used for authentication and authorization of applications and APIs.
+topics:
+ - api-authentication
+ - api-authorization
+ - oidc
+contentType: index
+useCase:
+ - secure-api
+ - call-api
+ - add-login
+---
+
+
+
+
Authentication and Authorization Flows
+
Introduction to the various flows used for authentication and authorization of applications and APIs.
+
+
+Auth0 uses [OpenID Connect (OIDC)](/protocols/oidc) and [OAuth 2.0](/protocols/oauth2) to authenticate users and get their authorization to access protected resources. With Auth0, you can easily support different flows in your own applications and APIs without worrying about the OAuth 2.0/OIDC specification or the other technical aspects of authentication and authorization.
+
+We support scenarios for server-side, mobile, desktop, client-side, machine-to-machine, and device applications.
+
+
+ Because regular web apps are server-side apps where the source code is not publicly exposed, they can use the Authorization Code Flow (defined in OAuth 2.0 RFC 6749, section 4.1), which exchanges an Authorization Code for a token.
+
+ During authentication, mobile and native applications can use the OAuth 2.0 Authorization Code Flow, but they require additional security. Additionally, single-page apps have special challenges. To mitigate these, OAuth 2.0 provides a version of the Authorization Code Flow which makes use of a Proof Key for Code Exchange (PKCE) (defined in OAuth 2.0 RFC 7636).
+
+ As an alternative to the Authorization Code Flow, the OAuth 2.0 spec includes the Implicit Flow intended for Public Clients, or applications which are unable to securely store Client Secrets. While this is no longer considered a best practice for requesting Access Tokens, when used with Form Post response mode, it does offer a streamlined workflow if the application needs only an ID Token to perform user authentication.
+
+ With machine-to-machine (M2M) applications, such as CLIs, daemons, or services running on your back-end, the system authenticates and authorizes the app rather than a user. For this scenario, typical authentication schemes like username + password or social logins don't make sense. Instead, M2M apps use the Client Credentials Flow (defined in OAuth 2.0 RFC 6749, section 4.4).
+
+ With input-constrained devices that connect to the internet, rather than authenticate the user directly, the device asks the user to go to a link on their computer or smartphone and authorize the device. This avoids a poor user experience for devices that do not have an easy way to enter text. To do this, device apps use the Device Authorization Flow (drafted in OAuth 2.0). For use with mobile/native applications.
+
diff --git a/articles/getting-started/_list-processes.md b/articles/getting-started/_list-processes.md
index 7b9dc2fa64..b8d018dc5a 100644
--- a/articles/getting-started/_list-processes.md
+++ b/articles/getting-started/_list-processes.md
@@ -1,31 +1,33 @@
<% if (screen === "dashboard") { %>
This is the dashboard home page. Here you can view statistics about your apps: the login activity for the past year, the logins and new signups for the past week, a list of the latest signups, and more.
[More docs on the dashboard](/dashboard).
-<% } else if (screen === "clients") { %>
+<% } else if (screen === "applications") { %>
Use this page to manage your applications. For every app of yours that you want to use Auth0, you should register an application here. You can create new applications, view your existing ones, review settings, enable connections, and more.
- [More info on applications](/clients).
+ [More info on applications](/applications).
<% } else if (screen === "apis") { %>
Use this page to manage your APIs. Here you can register a new API of yours, that you want to secure with Auth0, and manage your existing ones.
- [More info on APIs](/apis).
+ [More info on APIs](/api-auth).
<% } else if (screen === "sso") { %>
- Single Sign On (SSO) Integrations enable the use of external services for single sign-on. In this page you can see a list of the available external services that you can use, such as Office 365, Salesforce, and others. Here you can create a new SSO integration, find tutorials on how to configure it, and review and update the settings of a particular integration.
- [More info on SSO Integrations](/sso/integrations).
+ Single Sign-on (SSO) Integrations enable the use of external services for SSO. In this page you can see a list of the available external services that you can use, such as Office 365, Salesforce, and others. Here you can create a new SSO integration, find tutorials on how to configure it, and review and update the settings of a particular integration.
+ [More info on SSO Integrations](/integrations/sso).
<% } else if (screen === "connections") { %>
Use this page to manage the identity providers that you use to login to your apps. There are four types:
- - [Database](${manage_url}/#/connections/database): securely store and manage username / password credentials either in an Auth0 Database or in your own. To connect to an existing database you can use JavaScript scripts (we provide the templates) that run on Auth0's server on every authentication. Furthermore, you can migrate an existing legacy credentials database to Auth0 gradually as users authenticate (no password reset required). [More info on Database Connections](/connections/database).
- - [Social](${manage_url}/#/connections/social): configure social connections like Facebook, Twitter, Github and others, so that you can let your users login with them. [More info on individual social providers](/identityproviders#social).
- - [Enterprise](${manage_url}/#/connections/enterprise): configure Enterprise Connections like Active Directory, SAML, Office 365 and others so that you can let your users login with them. This way your users can use their enterprise credentials to login to your app. [More info on individual enterprise providers](/identityproviders#enterprise).
- - [Passwordless](${manage_url}/#/connections/passwordless): let your users signup and login using one-time codes (delivered by email or SMS) or one-click links, instead of passwords. [More info on Passwordless](/connections/passwordless).
-<% } else if (screen === "users") { %>
- This is where you manage your user's identities. In this page you can view your user's profiles, create new ones, perform password resets, block and delete users, and many more. You can also use this page to log in as any of your users in order to reproduce any issues that they report and debug your application. [More info on User Management](/users).
+ - [Database](${manage_url}/#/connections/database): Securely store and manage username / password credentials either in an Auth0 Database or in your own. To connect to an existing database you can use JavaScript scripts (we provide the templates) that run on Auth0's server on every authentication. Furthermore, you can migrate an existing legacy credentials database to Auth0 gradually as users authenticate (no password reset required). [More info on Database Connections](/connections/database).
+ - [Social](${manage_url}/#/connections/social): Configure social connections like Facebook, Twitter, Github and others, so that you can let your users login with them. [More info on individual social providers](/connections/identity-providers-social).
+ - [Enterprise](${manage_url}/#/connections/enterprise): Configure Enterprise Connections like Active Directory, SAML, Office 365 and others so that you can let your users login with them. This way your users can use their enterprise credentials to login to your app. [More info on individual enterprise providers](/connections/identity-providers-enterprise).
+ - [Passwordless](${manage_url}/#/connections/passwordless): Let your users signup and login using one-time codes (delivered by email or SMS) or one-click links, instead of passwords. [More info on Passwordless](/connections/passwordless).
+ <% } else if (screen === "universal-login") { %>
+ This is where you can create a beautiful universal login page where you can redirect to authenticate your users, customize the look and feel of your login page with CSS and HTML, and implement SSO in your applications with the flip of a switch. [More info on Universal Login](/universal-login).
+<% } else if (screen === "users-roles") { %>
+ This is where you manage your user's identities and permissions.
+ - [Users](${manage_url}/#/users): View your user's profiles, create new ones, perform password resets, block and delete users, and many more. [More info on Users](/users).
+ - [Roles](${manage_url}/#/roles): Create and manage roles for your applications. Roles contain collection of permissions and can be assigned to users. [More info on Roles](/authorization/guides/manage-roles).
<% } else if (screen === "rules") { %>
Here you can configure custom JavaScript snippets that are executed in Auth0 as part of the transaction every time a user authenticates to your application. You can call external APIs, filter which users can login to your application, use a whitelist, geolocated access or anything. [More information on Rules](/rules).
<% } else if (screen === "hooks") { %>
Here you can configure Node.js code that is executed against extensibility points (which are comparable to webhooks that come with a server). This way you can customize the behavior of Auth0 when you use Database Connections. [More info on Hooks](/hooks).
<% } else if (screen === "mfa") { %>
- Use this page to configure Multifactor Authentication (MFA) for your apps. This way you can add an additional factor to conventional logins to prevent unauthorized access. You can use Push Notifications, SMS or both. [More info on MFA](/multifactor-authentication).
-<% } else if (screen === "hlp") { %>
- Here you can create a login page where you can redirect to authenticate your users. The page can be customized with HTML and CSS and will be hosted by Auth0. By using centralized authentication, your app will be more secure and you will be able to implement SSO very easily. Except for the login, you can also add pages for the Password Reset process, MFA, and error pages. [More info on Hosted Pages](/hosted-pages).
+ Use this page to configure multi-factor authentication (MFA) for your apps. This way you can add an additional factor to conventional logins to prevent unauthorized access. You can use Push Notifications, SMS, Voice, etc. [More info on MFA](/mfa).
<% } else if (screen === "emails") { %>
Here you can configure the email templates for verification emails, welcome emails, change password emails, and more. You can also configure a custom SMTP email provider which is a requirement for production purposes. Auth0 does offer a built-in email infrastructure but it should be used for testing purposes only. [More info on emails](/email).
<% } else if (screen === "logs") { %>
@@ -35,5 +37,5 @@
<% } else if (screen === "extensions") { %>
In this page you can see a list of pre-built addons that we have created for you. You can use them to extend the functionality of the Auth0 base product. You can enable extensions in order to import or export users, export logs to external services, expose the Users dashboard to a group of users (without allowing them access to the rest of the dashboard), manage user authorization, and more. [More info on extensions](/extensions).
<% } else { %>
- The last screeen navigates you to our [Support Center](${env.DOMAIN_URL_SUPPORT}). The alternative to users that do not have access to support services is the [Auth0 Community](https://community.auth0.com/). [More info on support options](/support).
-<% } %>
\ No newline at end of file
+ The last screen navigates you to our [Support Center](${env.DOMAIN_URL_SUPPORT}). The alternative to users that do not have access to support services is the [Auth0 Community](https://community.auth0.com/). [More info on support options](/support).
+<% } %>
diff --git a/articles/getting-started/create-tenant.md b/articles/getting-started/create-tenant.md
new file mode 100644
index 0000000000..ecc9e1c324
--- /dev/null
+++ b/articles/getting-started/create-tenant.md
@@ -0,0 +1,36 @@
+---
+title: Create a Tenant
+description: Learn how to create a tenant in the Auth0 Dashboard.
+topics:
+ - tenants
+contentType: how-to
+useCase:
+ - create-tenant
+ - get-started
+---
+# Create a Tenant
+
+Once you create your account, you will be asked to create a **tenant**. No tenant can access the data of another tenant, even though multiple tenants might be running on the same machine.
+
+Tenant characteristics include:
+
+- The tenant name has to be unique. It will be used to create your personal domain.
+- The tenant name can contain only lowercase alphanumeric characters and hyphens ("-"). It cannot begin or end with a hyphen.
+- The tenant name must be a minimum of 3 characters and maximum of 64 characters.
+- The tenant name cannot be changed after creation.
+- You can create more than one tenant; in fact you are encouraged to do so for each environment you may have, such as development, staging, or production. For details, see [Set Up Multiple Environments](/dev-lifecycle/setting-up-env).
+
+When you name your tenant, that name becomes your Auth0 domain. (Or you can create a custom domain.) This domain is the base URL that you will use to access our API and the URL where your users are redirected to authenticate.
+
+Auth0 supports three regional subdomains:
+- `us.auth0.com` for US
+- `eu.auth0.com` for Europe
+- `au.auth0.com` for Australia
+
+When you you are asked for the region you want to use, your choice affects which regional subdomain will be assigned to you and where your data will be hosted. If you pick US, then the name format will be `YOUR-TENANT-NAME.us.auth0.com`; for Europe, it will be `YOUR-TENANT-NAME.eu.auth0.com`; and so forth.
+
+In our example, Example-Co chose the name `example-co` and **Americas** as their region. So their domain is `example-co.us.auth0.com`.
+
+## Keep reading
+
+* [Set Up Multiple Environments](/dev-lifecycle/setting-up-env)
diff --git a/articles/getting-started/dashboard-overview.md b/articles/getting-started/dashboard-overview.md
index d951a1d079..3528b0a344 100644
--- a/articles/getting-started/dashboard-overview.md
+++ b/articles/getting-started/dashboard-overview.md
@@ -2,6 +2,14 @@
title: Dashboard Overview
description: Learn the basics of the Auth0 Dashboard
toc: true
+topics:
+ - auth0-101
+ - dashboard
+contentType:
+ - how-to
+useCase:
+ - manage-accounts
+ - get-started
---
# Dashboard Overview
@@ -13,7 +21,7 @@ It consists of several sections which you can navigate using the sidebar menu on
## Configure your implementation
-The matrix that follows offers a brief overview of the different dashboard screens and what you can do on each.
+The following table contains a brief overview of the different dashboard pages and what you can do on each.
@@ -29,7 +37,7 @@ The matrix that follows offers a brief overview of the different dashboard scree
@@ -90,10 +98,10 @@ The matrix that follows offers a brief overview of the different dashboard scree
On the top right you can see your tenant's name and icon, and a little arrow. This arrow displays a drop-down menu that you can use to configure different aspects of your account:
+- **Settings**: Here you can configure several aspects of your tenant. For more info see [Tenant Settings in the Auth0 Dashboard](/dashboard/reference/settings-tenant).
+- **Invite an admin**: Use this option to add another person as admin to your tenant configuration. For more info see [Manage Admins in the Dashboard](/dashboard/manage-dashboard-admins).
+- **Create tenant**: Use this to [create a new tenant](/getting-started/create-tenant).
- **Switch tenant**: If you have multiple [tenants](/getting-started/the-basics#account-and-tenants) you can use this option to switch between them. All configuration described in the previous section is per tenant. If you create an application for `tenant-A`, you will not see it listed for `tenant-B`. If you have more than one tenant, you will find this switching option handy.
-- **Settings**: Here you can configure several aspects of your tenant. For more info see [Tenant Settings in the Auth0 Dashboard](/dashboard/dashboard-tenant-settings).
-- **Invite users to this tenant**: Use this option to add another person as admin to your tenant configuration. For more info see [Manage Admins in the Dashboard](/dashboard/manage-dashboard-admins).
-- **Create tenant**: Use this to [create a new tenant](/getting-started/the-basics#account-and-tenants).
- **View profile**: Use this to view information about your [account profile](${manage_url}/#/profile).
-- **Subscription overview**: This option navigates you to our [Account Center](${env.DOMAIN_URL_SUPPORT}/tenants/public) where you can see information about your subscription and your tenants.
-- **Log out**: Log out from your account.
\ No newline at end of file
+- **Account usage**: This option navigates you to our [Account Center](${env.DOMAIN_URL_SUPPORT}/tenants/public) where you can see information about your subscription and your tenants.
+- **Logout**: Log out from your account.
\ No newline at end of file
diff --git a/articles/getting-started/deployment-models.md b/articles/getting-started/deployment-models.md
index a6bef722b4..3f9a81a6cf 100644
--- a/articles/getting-started/deployment-models.md
+++ b/articles/getting-started/deployment-models.md
@@ -2,19 +2,43 @@
title: Auth0 Deployment Models
description: Read about the four different deployment models that Auth0 offers and the differences between them
toc: true
+topics:
+ - auth0-101
+ - deployment-models
+contentType:
+ - concept
+useCase:
+ - development
+ - get-started
---
# Auth0 Deployment Models
-Auth0 is offered in four deployment models:
+Auth0 is offered in the following deployment models:
-- As a **multi-tenant cloud service** running on Auth0's cloud
-- As a **dedicated cloud service** running on Auth0's cloud
-- As a **dedicated cloud service** running on Customer's cloud infrastructure
-- As an **on-premises virtual Private SaaS (PSaaS) Appliance** running on Customer's data centers
+
+
+
Deployment
+
Description
+
+
+
Public Cloud
+
A multi-tenant cloud service running on Auth0's cloud
+
+
+
Standard Private Cloud
+
A dedicated cloud service running on Auth0's cloud
+
+
+
Managed Private Cloud
+
A dedicated cloud service running on either Auth0's cloud or the customer's AWS cloud infrastructure
+
+
-::: note
-PSaaS Appliance is a managed service that you can use if your organization's requirements prevent you from using a multi-tenant cloud service. To learn more refer to [Private SaaS (PSaaS) Appliance](/appliance).
-:::
+The [Standard and the Managed Private Cloud](/private-cloud) options are managed services that you can use if:
+
+* Your organization's requirements prevent you from using the multi-tenant public cloud service
+* You require an SLA guaranteeing higher uptimes
+* You require a guaranteed level of requests per second
The following tables describe operational and feature differences between these models.
@@ -24,15 +48,15 @@ The following tables describe operational and feature differences between these
Where It Runs
-
Auth0's Infrastructure
-
Customer's Infrastructure
+
Auth0's Infrastructure
+
Auth0's Infrastructure
+
Auth0's Infrastructure or Customer's AWS Cloud
How It Runs
-
Multi-Tenant
-
Dedicated
-
Cloud
-
On-Premises
+
Public Cloud (Multi-Tenant)
+
Standard Private Cloud
+
Managed Private Cloud
@@ -40,172 +64,138 @@ The following tables describe operational and feature differences between these
Cumulative. Deployed post multi-tenant update after coordination with Customer.
-
Scheduled with Customer.
Minimum 1/month, except critical updates (such as vulnerabilities, security updates)
-
Scheduled with Customer.
Minimum 1/month, except critical updates (such as vulnerabilities, security updates)
+
Automatic Updates
+
Automatic Monthly Updates
+
Monthly, bi-monthly, or quarterly as coordinated with Auth0. Excludes critical updates (e.g., security patches), which will be applied as soon as possible
Deployment Configurations
N/A
-
High Availability (HA); Geo HA; High Capacity; Geo HA and High Capacity
-
High Availability (HA); Geo HA; High Capacity; Geo HA and High Capacity
+
High Availability (HA); High Capacity
High Availability (HA); Geo HA; High Capacity; Geo HA and High Capacity
500 requests per second with optional upgrade to 1500 requests per second
+
500 requests per second with optional upgrade to 1500 requests per second
+
+
+
Data Residency
+
Not applicable
+
Region of Choice*******
+
Region of Choice***
+
+
+
PCI Compliance
No
+
Add-on available
+
Add-on available for Auth0-Hosted Private Cloud
Support Channels & Levels
-
Same across all models
+
Same across all models
+
Same across all models
+
Same across all models
+*Access to the Managed Private Cloud can be restricted to customer's private subnets.
+
+**See the **PSaaS Appliance** section the Auth0 [Service Level Description](https://auth0.com/legal) (located under **Support Program and Service Levels**).
+
+***Deployments to China are currently unavailable.
+
+****If you need to meet data sovereignty requirements, Auth0 supports Private Cloud deployments in the following regions USA, Europe, Australia, Canada, and Japan. Otherwise, the Private Cloud can be supported in other regions (excepting China).
+
## Feature Differences
Available using SMS, Google Authenticator, Duo over TOTP/HOTP, and Push Notification with Guardian SDK.
-
Available using SMS, Google Authenticator, Duo over TOTP/HOTP, and Push Notification with Guardian SDK.
-
Available using SMS, Google Authenticator, Duo over TOTP/HOTP, and Push Notification with Guardian SDK.
-
-
-
Lock
-
Yes
-
Yes
-
Yes
-
Yes ***
-
-
-
Internet Restricted
-
No
-
No
-
No
-
Optional ***
+
Available using SMS, Voice, Google Authenticator or similar apps, Duo over TOTP/HOTP, Email, and Push Notification with Guardian
+
Available using SMS, Voice, Google Authenticator or similar apps, Duo over TOTP/HOTP, Email, and Push Notification with Guardian
-*See the [PSaaS Appliance: Extensions page](/appliance/extensions) to learn more about configuring extensions with the PSaaS Appliance.
-
-**See [PSaaS Appliance Custom Domains](/appliance/custom-domains) for details. If your PSaaS Appliance is hosted in the Auth0 Private Cloud, see [Private Cloud Requirements](/appliance/private-cloud-requirements).
-
-***You may choose to [operate the PSaaS Appliance in an Internet-restricted environment](/appliance/infrastructure/internet-restricted-deployment) (except during [update periods](/appliance/infrastructure/ip-domain-port-list#external-connectivity)).
\ No newline at end of file
+*See [Custom Domains](/appliance/custom-domains) and [Private Cloud Requirements](/appliance/private-cloud-requirements) for details.
diff --git a/articles/getting-started/faq.md b/articles/getting-started/faq.md
index b0cd2722cb..82bc9567db 100644
--- a/articles/getting-started/faq.md
+++ b/articles/getting-started/faq.md
@@ -2,5 +2,11 @@
description: FAQ for Auth0 beginners
toc: true
public: false
+topics:
+ - auth0-101
+contentType: concept
+useCase:
+ - strategize
+ - get-started
---
# Frequently Asked Questions - UNDER CONSTRUCTION
diff --git a/articles/getting-started/hello-world.md b/articles/getting-started/hello-world.md
index 47162e0187..28e11867a5 100644
--- a/articles/getting-started/hello-world.md
+++ b/articles/getting-started/hello-world.md
@@ -2,5 +2,11 @@
description: How to add authentication to a simple Hello World app using Auth0
toc: true
public: false
+topics:
+ - auth0-101
+contentType: tutorial
+useCase:
+ - strategize
+ - get-started
---
# Hello World - UNDER CONSTRUCTION
diff --git a/articles/getting-started/index.md b/articles/getting-started/index.md
index 46ab091b2d..a033710ec9 100644
--- a/articles/getting-started/index.md
+++ b/articles/getting-started/index.md
@@ -1,29 +1,25 @@
---
description: If you are new to Auth0 start here for a list of resources that can get you started
-title: Getting Started
+title: Get Started
classes: topic-page
+topics:
+ - auth0-101
+contentType:
+ - concept
+ - index
+useCase:
+ - strategize
+ - get-started
---
-
Getting Started
+
Get Started
Learn the basics of Auth0.
-Welcome! If you are new to Auth0, you are in the right place.
-
-This is an introduction to Auth0, and covers things like:
-
-* What is it we do
-* How we can help you
-* The basic terminology we use
-* The process of implementing Auth0
-* The Auth0 ecosystem
-* ... and many more
-
-Let's get started!
-
+Welcome! If you are new to Auth0, you are in the right place. Here we will cover how to get started using Auth0.
The Dashboard is where you configure and manage all things Auth0. This article offers a brief overview of the sections it contains and what you can do in each section.
Read about the four different deployment models that Auth0 offers.
+
Read about the four deployment models that Auth0 offers.
diff --git a/articles/getting-started/overview.md b/articles/getting-started/overview.md
index 72eb99f382..738d3bbd98 100644
--- a/articles/getting-started/overview.md
+++ b/articles/getting-started/overview.md
@@ -1,56 +1,59 @@
---
title: Auth0 Overview
-description: Learn what Auth0 is and how you can use it
+description: Learn what Auth0 is and how you can use it.
toc: true
+topics:
+ - auth0-101
+ - auth0-overview
+contentType: concept
+useCase:
+ - strategize
+ - get-started
---
# Auth0 Overview
-Auth0 provides authentication and authorization as a service.
-
-We are here to give developers and companies the building blocks they need in order to secure their applications, without having to become security experts.
+Auth0 is a flexible, drop-in solution to add authentication and authorization services to your applications. Your team and organization can avoid the cost, time, and risk that comes with building your own solution to authenticate and authorize users.
You can connect any application (written in any language or on any stack) to Auth0 and define the identity providers you want to use (how you want your users to log in).
-Based on your app's technology, choose one of our SDKs (or call our API) and hook it up to your app. Now each time a user tries to authenticate, Auth0 will verify their identity and send the required information back to your app.
-
-
+Based on your app's technology, choose one of our SDKs (or call our API), and hook it up to your app. Now each time a user tries to authenticate, Auth0 will verify their identity and send the required information back to your app.
## Why use Auth0?
-Take a look at just a few of the use cases for which you can use Auth0:
+Take a look at just a few of Auth0's use cases:
-- You built an awesome app and you want to add user authentication and authorization. Your users should be able to log in either with username/password or with their social accounts (Facebook, Twitter, and so on). You want to retrieve the user's profile after the login so you can customize the UI and apply your authorization policies.
+- You built an awesome app and you want to add user authentication and authorization. Your users should be able to log in either with username/password or with their social accounts (such as Facebook or Twitter). You want to retrieve the user's profile after the login so you can customize the UI and apply your authorization policies.
- You built an API and you want to secure it with [OAuth 2.0](/protocols/oauth2).
-- You have more than one app and you want to implement [Single Sign On](/sso).
-- You built a JavaScript front-end app and a mobile app and you want them both to securely access your API.
-- You have a web app which needs to authenticate users using SAML.
+- You have more than one app, and you want to implement Single Sign-on (SSO).
+- You built a JavaScript front-end app and a mobile app, and you want them both to securely access your API.
+- You have a web app which needs to authenticate users using Security Assertion Markup Language (SAML).
- You believe passwords are broken and you want your users to log in with one-time codes delivered by email or SMS.
-- If one of your user's email addresses is compromised in some site's public data breach, you want to be notified, and also notify the users and/or block them from logging in to your app until they reset their password.
-- You want to act proactively and block suspicious IP addresses if they make consecutive failed login attempts, in order to avoid DDoS attacks.
+- If one of your user's email addresses is compromised in some site's public data breach, you want to be notified, and you want to notify the users and/or block them from logging in to your app until they reset their password.
+- You want to act proactively to block suspicious IP addresses if they make consecutive failed login attempts, in order to avoid DDoS attacks.
- You are part of a large organization who wants to federate their existing enterprise directory service to allow employees to log in to the various internal and third-party applications using their existing enterprise credentials.
- You don't want (or you don't know how) to implement your own user management solution. Password resets, creating, provisioning, blocking, and deleting users, and the UI to manage all these. You just want to focus on your app.
-- You want to enforce [multifactor authentication](/multifactor-authentication) when your users want to access sensitive data.
-- You are looking for an identity solution that will help you stay on top of the constantly growing compliance requirements of SOC2, GDPR, OpenID Connect and others.
-- You want to use analytics to track users on your site or application. You plan on using this data to create funnels, measure user retention, and improve your sign up flow.
+- You want to enforce multi-factor authentication (MFA) when your users want to access sensitive data.
+- You are looking for an identity solution that will help you stay on top of the constantly growing compliance requirements of SOC2, GDPR, PCI DSS, HIPAA, and others.
+- You want to use analytics to track users on your site or application. You plan on using this data to create funnels, measure user retention, and improve your sign-up flow.
## Which industry standards does Auth0 use?
-Once upon a time, when computers were standalone systems, all the authentication and user data lived in a single machine. Times have changed, and now you can use the same login information across multiple apps and sites. This was achieved due to the identity industry standards that were widely adopted across the web.
+Once upon a time, when computers were standalone systems, all the authentication and user data lived in a single machine. Times have changed, and now you can use the same login information across multiple apps and sites. This has been achieved through widespread adoption of identity industry standards across the web.
These are a set of open specifications and protocols that specify how to design an authentication and authorization system. They specify how you should manage identity, move personal data securely, and decide who can access applications and data.
The identity industry standards that we use here in Auth0 are:
-- **OAuth 1**: the original standard for access delegation. Used as a way for a user to grant websites access to their information on other websites or apps, but without giving them the credentials.
-- **OAuth 2**: an authorization standard that allows a user to grant limited access to their resources on one site, to another site, without having to expose their credentials. You use this standard every time you log in to a site using your Google account and you are asked if you agree with sharing your email address and your contacts list with that site.
-- **Open ID Connect**: an identity layer that sits on top of OAuth 2 and allows for easy verification of the user's identity, as well the ability to get basic profile information from the identity provider.
-- **JSON Web Tokens**: an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
+- **Open Authorization (OAuth) 1**: the original standard for access delegation. Used as a way for a user to grant websites access to their information on other websites or apps, but without giving them the credentials.
+- **Open Authorization (OAuth) 2**: an authorization standard that allows a user to grant limited access to their resources on one site, to another site, without having to expose their credentials. You use this standard every time you log in to a site using your Google account and you are asked if you agree with sharing your email address and your contacts list with that site.
+- **OpenID Connect (OIDC)**: an identity layer that sits on top of OAuth 2 and allows for easy verification of the user's identity, as well the ability to get basic profile information from the identity provider.
+- **JSON Web Tokens (JWT)**: an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object.
- **Security Assertion Markup Language (SAML)**: an open-standard, XML-based data format that allows businesses to communicate user authentication and authorization information to partner companies and enterprise applications their employees may use.
-- **WS-Federation**: a standard developed by Microsoft, and used extensively in their applications. It defines the way security tokens can be transported between different entities to exchange identity and authorization information.
+- **WS-Federation (WS-Fed)**: a standard developed by Microsoft, and used extensively in their applications. It defines the way security tokens can be transported between different entities to exchange identity and authorization information.
## Keep reading
::: next-steps
-- [Learn the basics and familiarize yourself with the identity terminology](/getting-started/the-basics)
-- [Read about the four different deployment models that Auth0 offers](/getting-started/deployment-models)
+- [Learn the basics and familiarize yourself with identity terminology](/getting-started/the-basics)
+- [Read about different deployment models offered by Auth0](/getting-started/deployment-models)
:::
diff --git a/articles/getting-started/set-up-api.md b/articles/getting-started/set-up-api.md
new file mode 100644
index 0000000000..cb5c67c61f
--- /dev/null
+++ b/articles/getting-started/set-up-api.md
@@ -0,0 +1,101 @@
+---
+title: Set Up an API
+description: Learn how to set up an API in Auth0 Dashboard.
+topics:
+ - apis
+contentType: how-to
+useCase:
+ - set-up-api
+ - get-started
+---
+# Set Up an API
+
+1. In the Dashboard, click on the [APIs menu option](${manage_url}/#/apis) on the left.
+
+ ::: note
+ The API tab will already have one API created automatically, the **Auth0 Management API**. For more details on the features of the Management API and its available endpoints, refer to: [Management API](/api/management/v2).
+ :::
+
+2. Click the **+ Create API** button.
+
+ 
+
+ You need to provide the following information for your API:
+
+ - **Name**: a friendly name for the API. Does not affect any functionality.
+
+ - **Identifier**: a unique identifier for the API. Auth0 recommends using a URL. Auth0 does differentiate between URLs that include the last forward slash. For example, https://example.com and https://example.com/ are two different identifiers. The URL does not have to be a publicly available URL. Auth0 will not call your API. This value **cannot** be modified afterwards.
+
+ - **Signing Algorithm**: the algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting `RS256` the token will be signed with the tenant's private key. To learn more about signing algorithms, see [Signing Algorithms](/tokens/concepts/signing-algorithms).
+
+3. Fill in the required information and click the **Create** button.
+
+ Once you do so you will be navigated to the *Quick Start* of your API. Here you can find details on the implementation changes you have to do to your API, which basically consists of choosing a JWT library from a predefined list and configuring this library to validate the Access Tokens in your API.
+
+ 
+
+ The other available views for your API are:
+
+ - **Settings**: lists the settings for your API. Some are editable. Here you can change the token expiration time and enable offline access (this way Auth0 will allow your applications to ask for Refresh Tokens for this API). For details refer to the [API Settings paragraph](#api-settings).
+
+ - **Scopes**: here you can define the scopes for this API, by setting a name and a description.
+
+ - **Machine to Machine Applications**: lists all applications for which the **Client Credentials** grant is **enabled**. By default, this grant is **enabled* for [Regular Web Applications and Machine to Machine Applications](/applications). You can authorize any of these applications to request Access Tokens for your API. Optionally, you can select a subset of the defined scopes to limit your authorized application's access.
+
+ - **Test**: from this view, you can execute a sample Client Credentials flow with any of your authorized applications to check that everything is working as expected.
+
+## API settings
+
+Click on the **Settings** tab of your [API](${manage_url}/#/apis) to review the available settings:
+
+- **Id**: A unique alphanumeric string generated by Auth0. The information is read only and you will only need it if you will be working directly with [Auth0's Management API Resource Servers endpoints](/api/management/v2#!/Resource_Servers/get_resource_servers_by_id).
+
+- **Name**: A friendly name for the API. Does not affect any functionality. The following characters are not allowed: `< >`.
+
+- **Identifier**: A unique identifier for your API. This value is set upon API creation and cannot be modified afterwards. We recommend using a URL but note that this doesn't have to be a publicly available URL, Auth0 will not call your API at all.
+
+- **Token Expiration (Seconds)**: The amount of time (in seconds) before the Auth0 Access Token expires. The default value is 86400 seconds (24 hours). The maximum value you can set is 2592000 seconds (30 days).
+
+- **Allow Skipping User Consent**: When a first party application requests authorized access against an API with the *Allow Skipping User Consent* flag set, the User Consent dialog will not be shown to the final user. Note that if the hostname of your application's **callback URL** is `localhost` or `127.0.0.1` the consent dialog will always be displayed.
+
+- **Allow Offline Access**: If this setting is enabled, Auth0 will allow applications to ask for Refresh Tokens for this API.
+
+- **Signing Algorithm**: The algorithm to sign the tokens with. The available values are `HS256` and `RS256`. When selecting `RS256` (recommended) the token will be signed with the tenant's private key. This value is set upon API creation and cannot be modified afterwards. For more details on the signing algorithms see the [Signing Algorithms paragraph](#signing-algorithms) below.
+
+## Signing algorithms
+
+When you create an API you have to select the algorithm your tokens will be signed with. The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
+
+::: note
+The signature is part of a JWT. If you are not familiar with the JWT structure, please see [JSON Web Tokens (JWTs) in Auth0](/jwt#what-is-the-json-web-token-structure-).
+:::
+
+To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. That algorithm, which is part of the JWT header, is the one you select for your API: `HS256` or `RS256`.
+
+- **RS256** is an [asymmetric algorithm](https://en.wikipedia.org/wiki/Public-key_cryptography) which means that there are two keys: one public and one private (secret). Auth0 has the secret key, which is used to generate the signature, and the consumer of the JWT has the public key, which is used to validate the signature.
+
+- **HS256** is a [symmetric algorithm](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which means that there is only one secret key, shared between the two parties. The same key is used both to generate the signature and to validate it. Special care should be taken in order for the key to remain confidential.
+
+The most secure practice, and our recommendation, is to use **RS256**. Some of the reasons are:
+
+- With RS256 you are sure that only the holder of the private key (Auth0) can sign tokens, while anyone can check if the token is valid using the public key.
+
+- Under HS256, if the secret key is compromised (e.g. by the application) you would have to re-deploy the API with the new secret.
+
+- With RS256 you can request a token that is valid for multiple audiences.
+
+- With RS256 you can implement key rotation without having to re-deploy the API with the new secret.
+
+::: panel Verify an RS256 signed token
+Go to [Dashboard > Applications](${manage_url}/#/applications). Open the **Settings** of your applications, scroll down and open **Advanced Settings**. Open the **Certificates** tab and you will find the Public Key in the **Signing Certificate** field.
+
+If you want to use the Public Key to verify a JWT signature on [JWT.io](https://jwt.io/), you can copy the Public Key and paste it in the **Public Key or Certificate** field under the **Verify Signature** section on the [JWT.io](https://jwt.io/) website.
+
+If you want to verify the signature of a token from one of your applications, we recommend that you get the Public Key from your tenant's [JSON Web Key Set (JWKS)](/tokens/concepts/jwks). Your tenant's JWKS is `https://${account.namespace}/.well-known/jwks.json`.
+:::
+
+# Keep reading
+
+- [API Authorization Overview](/api-auth)
+- [Which OAuth Flow to Use](/api-auth/which-oauth-flow-to-use)
+- [Tokens](/tokens)
diff --git a/articles/getting-started/set-up-app/index.md b/articles/getting-started/set-up-app/index.md
new file mode 100644
index 0000000000..c289ac8edc
--- /dev/null
+++ b/articles/getting-started/set-up-app/index.md
@@ -0,0 +1,21 @@
+---
+title: Set Up an App
+description: Learn how to set up an app in Auth0 Dashboard.
+classes: topic-page
+topics:
+ - apps
+contentType: how-to
+useCase:
+ - set-up-app
+ - get-started
+---
+# Set Up an App
+
+Learn how to set up an app in the Auth0 Dashboard. You can set up the following app types:
+
+<%= include('../../_includes/_topic-links', { links: [
+ 'dashboard/guides/applications/register-app-regular-web',
+ 'dashboard/guides/applications/register-app-native',
+ 'dashboard/guides/applications/register-app-spa',
+ 'dashboard/guides/applications/register-app-m2m',
+] }) %>
diff --git a/articles/getting-started/the-authentication-flow.md b/articles/getting-started/the-authentication-flow.md
index 26238ad8b6..b91140b4c8 100644
--- a/articles/getting-started/the-authentication-flow.md
+++ b/articles/getting-started/the-authentication-flow.md
@@ -2,5 +2,12 @@
description: Learn how the Auth0 authentication flow works
toc: true
public: false
+topics:
+ - auth0-101
+ - authentication
+contentType: concept
+useCase:
+ - development
+ - get-started
---
# The Authentication Flow - UNDER CONSTRUCTION
diff --git a/articles/getting-started/the-basics.md b/articles/getting-started/the-basics.md
index fb1d91c58e..ed84b63202 100644
--- a/articles/getting-started/the-basics.md
+++ b/articles/getting-started/the-basics.md
@@ -1,46 +1,70 @@
---
title: Learn the Basics
-description: Learn the basics of Auth0 and familiarize yourself with the terminology
+description: Learn the basics of Auth0 and familiarize yourself with the terminology.
toc: true
+topics:
+ - auth0-101
+ - auth0-basics
+contentType: concept
+useCase:
+ - development
+ - strategize
+ - get-started
---
# Learn the Basics
-Often, the biggest barrier to learning new things, especially in the tech industry, is terminology. The words that are used to describe things can cause problems when you try to understand new concepts. This document explains some of the basic terminology we use here at Auth0, and maps these terms to concepts you are already familiar with.
+Often, the biggest barrier to learning new things, especially in the tech industry, is terminology. The words that are used to describe things can cause problems when you try to understand new concepts. This document explains some of the basic terminology we use here at Auth0, and maps these terms to concepts you are already familiar with. We also have a handy [glossary](/glossary).
::: panel TL;DR
-This article uses an example to introduce some core concepts of Auth0: **accounts**, **tenants**, **domains**, **applications**, and **connections**. If you already know what these are (in the context of Auth0) you can safely skip reading it.
+This article uses an example to introduce some core concepts of Auth0: **accounts**, **tenants**, **domains**, **applications**, and **connections**. If you already know what these are in the context of Auth0, you can safely skip reading it.
-We will use a very simple example: A company named `Example-Co` wants to use Auth0 for authentication. They have a web app and a mobile app, and they want their users to be able to login with username/password, Google, or GitHub.
+We will use a very simple example: A company named `Example-Co` wants to use Auth0 for authentication. They have a web app and a mobile app, and they want their users to be able to log in with username/password, Google, or GitHub.
:::
## Account and tenants
-If you haven't already signed up for an Auth0 **account**, do so (it's free). You can either use username/password or log in with a social provider (GitHub, Google, or Microsoft).
+If you haven't already [signed up](https://auth0.com/signup) for an Auth0 **account**, do so (it's free). You can either use username and password or log in with a social provider (such as Facebook, Google, or Apple).
-Once you create your account you will be asked to create a **Tenant**. This is a **logical isolation unit**.
+Once you create your account you will be asked to create a tenant. *Tenant* is a term borrowed from [software multitenancy](https://en.wikipedia.org/wiki/Multitenancy). It refers to an architecture where a single software instance serves multiple tenants. In Auth0, a tenant is logically isolated. No tenant can access the data of another tenant, even though multiple tenants might be running on the same machine.
-The term is borrowed from "software multitenancy". This refers to an architecture where a single instance of the software serves multiple tenants. No tenant can access the instance of another tenant, even though the software might be running on the same machine (hence the logical isolation).
+Tenant characteristics:
-Some characteristics:
-
-- The tenant name has to be unique (we will see in the next paragraph that it is used to create your own personal domain).
+- The tenant name has to be unique. It will be used to create your personal domain.
+- The tenant name can contain only lowercase alphanumeric characters and hyphens ("-"). It cannot begin or end with a hyphen.
+- The tenant name must be a minimum of three characters and maximum of 64 characters.
- The tenant name cannot be changed after creation.
- You can create more than one tenant; in fact, you are encouraged to do so for each environment you have (such as Development, Staging, or Production).
-- If you chose to host your data in Europe or Australia, then your tenant will have a suffix (`eu` or `au`). In our example, if `Example-Co` picked the name `example-co`, then depending on where the data is stored, the tenant name would be `example-co-eu` or `example-co-au`.
-## Domain
+You can create additional tenants at any time. To do so, go to the upper-right corner of the Dashboard and click on your tenant name to display the pulldown menu. Click **Create Tenant**.
-As discussed in the previous section, when you create a new account with Auth0, you are asked to pick a name for your **Tenant**. This name, appended with `auth0.com`, will be your Auth0 **Domain**. It's the base URL you will be using when you want to access our API (for example, to authenticate a user). The name format is `TENANT-NAME.auth0.com` (you get to pick the `TENANT-NAME` part).
+## Domains
-In our example, `Example-Co` picked the name `example-co`; hence their domain is `example-co.auth0.com`.
+As discussed in the previous section, when you create a new account with Auth0, you are asked to pick a name for your tenant. This name, appended with `auth0.com`, will be your Auth0 *domain*. (You can also use [custom domains](#custom-domains).) It's the base URL you will use to access our API and the URL where your users are redirected in order to authenticate.
-::: panel Custom Domains
-You can use a custom domain, such as `example-co.com`. This comes with an additional cost. This feature is in beta for **public-cloud tenants** (see the [Custom Domains](/custom-domains) documentation for details). If you have a **single-tenant** implementation, you can deploy your custom domain in one of three locations:
-- The cloud managed by Auth0
-- A cloud managed by you
-- An [on-premise installation](/appliance)
+Auth0 supports three regional subdomains:
+- `us.auth0.com` for US
+- `eu.auth0.com` for Europe
+- `au.auth0.com` for Australia
+
+When you create your tenant, you are asked for the region you want to use. This choice affects which regional subdomain will be assigned to you and where your data will be hosted. So if you pick US then the name format will be `YOUR-TENANT-NAME.auth0.com`, for Europe it will be `YOUR-TENANT-NAME.eu.auth0.com`, and so forth.
+
+In our example, `Example-Co` picked the name `example-co` and Americas as their region. Therefore their domain is `example-co.auth0.com`.
+
+::: note
+Tenants created on or after 10 June 2020 in the US region will be appended with `us.auth0.com` (instead of `auth0.com`) to create the domain URL that you use to access Auth0 services.
:::
+### Custom domains
+
+We recommend the use of custom domains, such as `example-co.com`, in your production environments to provide your users with the most secure and seamless experience. This comes with an additional cost.
+
+If you have a [**single-tenant** implementation](/private-cloud), you can deploy your custom domain in:
+
+- The cloud managed by Auth0
+- An AWS cloud managed by you
+
+For more information, see [Custom Domains](/custom-domains).
+
## Application
Now that you have an account, we need to know about your app(s) that will be using our services. To that end, you must register each application. We use the term **application** to refer to an application (like [OAuth 2.0 does](https://tools.ietf.org/html/rfc6749#page-6)).
@@ -70,9 +94,9 @@ This relationship between Auth0 and the identity provider is referred to as a **
Connections are sources of users and they can be of the following types:
- [Database connections](/connections/database): Users log in with username and passwords, stored either in the Auth0 cloud or your own database
-- [Social logins](/identityproviders#social): Google, Facebook, Twitter, and more
-- [Enterprise directories](/identityproviders#enterprise): LDAP, Google Apps, Office 365, ADFS, AD, SAML-P, WS-Federation, and more
-- [Passwordless systems](/connections/passwordless): Users log in with one-time codes, sent via SMS or email
+- [Social logins](/connections/identity-providers-social): Google, Facebook, Twitter, and more
+- [Enterprise directories](/connections/identity-providers-enterprise): LDAP, G Suite, Office 365, ADFS, AD, SAML-P, WS-Federation, and more
+- [Passwordless systems](/connections/passwordless): Users log in with one-time codes, sent via SMS or email
Each connection can be shared among multiple applications. You can configure any number of connections, and then choose which of them to enable for each application.
@@ -84,7 +108,7 @@ In our example, `ExampleCo` wants their users to be able to login with username/
1. Enable all three connections for the mobile app
::: note
-For more information on the supported identity providers, refer to [Identity Providers Supported by Auth0](/identityproviders). For details on how to enable a connection for an application, refer to [Application Connections](/applications/connections).
+For more information on the supported identity providers, refer to [Identity Providers Supported by Auth0](/identityproviders). For details on how to enable a connection for an application, refer to [Connections](/connections).
:::
## Where to go from here
@@ -95,13 +119,11 @@ If you wish to learn more about the next steps in setting up Auth0, you can read
- **Hook Auth0 up to your app**: Assuming that your app has a login and a logout button, you need to add some code in order to invoke Auth0 APIs each time one of these buttons is clicked. For details you can refer to one of our [quickstarts](/quickstarts). Alternatively, you can directly call our API to [log in](/api/authentication#login) or [log out](/api/authentication#logout) a user, or implement one of Auth0's [libraries and SDKs](/libraries).
-- **Migrate your users to Auth0**: If you already have a user store, you need to migrate these users to Auth0 before you go live. For more information refer to [User Migration](/users/migrations). Alternatively, you can [connect your app to your own user database](/connections/database/custom-db) and access it via Auth0.
+- **Migrate your users to Auth0**: If you already have a user store, you need to migrate these users to Auth0 before you go live. For more information refer to [User Migration](/users/concepts/overview-user-migration). Alternatively, you can [connect your app to your own user database](/connections/database/custom-db) and access it via Auth0.
## Keep reading
-::: next-steps
-- [Learn how you can configure, secure, and access your own API with Auth0](/apis)
-- [Learn more about Auth0 APIs](/api/info)
-- [Learn about our libraries](/libraries)
-- [Learn about working with users and user profiles in Auth0](/users)
-:::
\ No newline at end of file
+- [Auth0 APIs](/api/info) - Learn about Auth0 APIs.
+- [Set Up an API](/getting-started/set-up-api) - Learn how to configure your own API with Auth0.
+- [Auth0 Libraries & SDKs](/libraries) - Learn about our libraries and SDKs.
+- [Manage Users](/users) - Learn about working with users and user profiles in Auth0.
diff --git a/articles/getting-started/the-implementation-process.md b/articles/getting-started/the-implementation-process.md
index 2470d48cbb..832eefbc0f 100644
--- a/articles/getting-started/the-implementation-process.md
+++ b/articles/getting-started/the-implementation-process.md
@@ -2,21 +2,27 @@
description: Roadmap of what you need to do to add authentication to your app and secure your APIs with Auth0
toc: true
public: false
+topics:
+ - auth0-101
+ - auth0-basics
+contentType: concept
+useCase:
+ - strategize
+ - development
+ - get-started
---
# The Implementation Process - UNDER CONSTRUCTION
## Integrate Auth0 with your Application
-The default [protocol](/protocols) between your application and Auth0 is [OpenID Connect](/protocols/oidc), a modern, lightweight, simple to use, and simple to integrate protocol.
-
-<%= include('../_includes/_pipeline2') %>
+The default [protocol](/protocols) between your application and Auth0 is [OpenID Connect (OIDC)](/protocols/oidc), a modern, lightweight, simple to use, and simple to integrate protocol.
Auth0 ships [SDKs for all major platforms](/support/matrix#sdks) (.NET, Java, PHP, Python, node, iOS, and many more), but the use of Auth0 SDKs is not required. Virtually anything able to send HTTP requests can integrate with Auth0.
-Auth0 also supports other common identity protocols, such as [WS-Federation](/protocols/ws-fed) and [SAML](/protocols/saml). Applications that are already "claims enabled" can easily connect to Auth0.
+Auth0 also supports other common identity protocols, such as [WS-Federation](/protocols/ws-fed) and [SAML](/protocols/saml). Applications that are already "claims enabled" can easily connect to Auth0.
-The **best** solution for integrating Auth0 with your application is to use Auth0's [universal login](/hosted-pages/login). Using universal login is a much less complicated process, and circumvents the dangers of cross-origin authentication. Universal login uses the [Lock](/libraries/lock) widget to allow your users to authenticate by default, but has other starting templates as well. You can customize the login page in the [Dashboard](${manage_url}/#/login_page).
+The **best** solution for integrating Auth0 with your application is to use Auth0's Universal Login. Using Universal Login is a much less complicated process, and circumvents the dangers of cross-origin authentication. Universal Login uses the [Lock](/libraries/lock) widget to allow your users to authenticate by default, but has other starting templates as well. You can customize the login page in the [Dashboard](${manage_url}/#/login_page).
## Access your APIs
-Auth0's [API authorization](/api-auth) features allow you to manage the authorization requirements for server-to-server and client-to-server applications, using the [OAuth 2.0 protocol](/protocols/oauth2). Using Auth0, you can easily support [different flows](/api-auth/which-oauth-flow-to-use) in your own APIs without worrying about the OAuth 2.0/OpenID Connect specification, or the many other technical aspects of API authorization.
\ No newline at end of file
+Auth0's [API authorization](/api-auth) features allow you to manage the authorization requirements for server-to-server and client-to-server applications, using the [OAuth 2.0 protocol](/protocols/oauth2). Using Auth0, you can easily support [different flows](/api-auth/which-oauth-flow-to-use) in your own APIs without worrying about the OAuth 2.0/OpenID Connect specification, or the many other technical aspects of API authorization.
diff --git a/articles/getting-started/whats-next.md b/articles/getting-started/whats-next.md
index 699e378d16..a2ed17b47d 100644
--- a/articles/getting-started/whats-next.md
+++ b/articles/getting-started/whats-next.md
@@ -2,6 +2,14 @@
description: Learn about Auth0 advanced features
toc: true
public: false
+topics:
+ - auth0-101
+ - auth0-basics
+contentType: concept
+useCase:
+ - strategize
+ - development
+ - get-started
---
# What's Next? - UNDER CONSTRUCTION
@@ -9,8 +17,8 @@ public: false
Auth0 offers several ways to extend the platform's functionality:
-- **Rules**: [Rules](/rules) are functions written in JavaScript or C#, that are executed in Auth0 just after successful authentication and before control returns to your app. Rules can be chained together for modular coding and can be turned on and off individually. They can be used for Access Control, Webhooks, Profile Enrichment, Multi-factor Authentication, and many other things.
+- **Rules**: [Rules](/rules) are functions written in JavaScript or C#, that are executed in Auth0 just after successful authentication and before control returns to your app. Rules can be chained together for modular coding and can be turned on and off individually. They can be used for Access Control, Webhooks, Profile Enrichment, Multi-factor Authentication (MFA), and many other things.
-- **Hooks**: [Hooks](/hooks) allow you to customize the behavior of Auth0 using Node.js code that is executed against extensibility points (which are comparable to webhooks that come with a server). They are [Webtasks](https://webtask.io) associated with specific [extensibility points](/hooks/extensibility-points) of the Auth0 platform. Auth0 invokes the Hooks at runtime to execute your custom logic. Hooks will eventually replace Rules, the current Auth0 extensibility method. Currently, you can use both Hooks and Rules, but Auth0 will implement new functionality in Hooks.
+- **Hooks**: [Hooks](/hooks) allow you to customize the behavior of Auth0 using Node.js code that is executed against extensibility points (which are comparable to webhooks that come with a server). They are secure, self-contained functions associated with specific [extensibility points](/hooks/extensibility-points) of the Auth0 platform. Auth0 invokes the Hooks at runtime to execute your custom logic. Hooks will eventually replace Rules, the current Auth0 extensibility method. Currently, you can use both Hooks and Rules, but Auth0 will implement new functionality in Hooks.
-- **Extensions**: [Auth0 Extensions](/extensions) enable you to install applications or run commands/scripts that extend the functionality of the Auth0 base product. You can either use one of the [pre-defined extensions](/extensions#using-an-auth0-provided-extension), provided by Auth0, or [create your own](/extensions#creating-your-own-extension). Some of the actions you can do with extensions are manage the authorizations for users (using groups, roles and permissions), import/export users, export logs to other services, deploy scripts from external repositories, and more.
\ No newline at end of file
+- **Extensions**: [Auth0 Extensions](/extensions) enable you to install applications or run commands/scripts that extend the functionality of the Auth0 base product. You can either use one of the [pre-defined extensions](/extensions#using-an-auth0-provided-extension), provided by Auth0, or [create your own](/extensions#creating-your-own-extension). Some of the actions you can do with extensions are manage the authorizations for users (using groups, roles, and permissions), import/export users, export logs to other services, deploy scripts from external repositories, and more.
\ No newline at end of file
diff --git a/articles/guides/ip-whitelist.md b/articles/guides/ip-whitelist.md
new file mode 100644
index 0000000000..093624e73e
--- /dev/null
+++ b/articles/guides/ip-whitelist.md
@@ -0,0 +1,55 @@
+---
+title: Whitelist IP Addresses
+description: Identify Auth0 IP addresses to whitelist if you are behind a firewall.
+topics:
+ - connections
+ - custom-database
+ - scripts
+contentType:
+ - reference
+ - how-to
+useCase:
+ - customize-connections
+---
+
+# Whitelist IP Addresses
+
+If you are behind a firewall, the following features may require whitelisting of the appropriate Auth0 IP addresses to ensure proper functionality:
+
+* [Custom Database Connections](/connections/database/custom-db)
+* [Hooks](/hooks)
+* [Rules](/rules)
+
+## Outbound Calls
+
+::: warning
+Please note that IP addresses are subject to change. In the event of a change, Auth0 will send notifications several months before any IP address changes take place. The lists provided are up-to-date at the time of writing, but check the [Dashboard](${manage_url}) for the latest list.
+:::
+
+When Auth0 makes outbound calls, the IP addresses are static. Auth0 translates internal IP addresses to one of the displayed options when reaching out using NAT.
+
+Please be sure to **allow** inbound connections from the region-specific set of IP addresses listed in the [Dashboard](${manage_url}). The specific set of IP addresses you should use is provided when you create your new [Custom Database Connection](${manage_url}/#/connections/database), [Hook](${manage_url}/#/hooks), or [Rule](${manage_url}/#/rules/create).
+
+The IP addresses are region-specific.
+
+### United States
+
+```text
+35.167.74.121, 35.166.202.113, 35.160.3.103, 54.183.64.135, 54.67.77.38, 54.67.15.170, 54.183.204.205, 35.171.156.124, 18.233.90.226, 3.211.189.167, 18.232.225.224, 34.233.19.82, 52.204.128.250, 3.132.201.78, 3.19.44.88, 3.20.244.231
+```
+
+### Europe
+
+```text
+52.28.56.226, 52.28.45.240, 52.16.224.164, 52.16.193.66, 34.253.4.94, 52.50.106.250, 52.211.56.181, 52.213.38.246, 52.213.74.69, 52.213.216.142, 35.156.51.163, 35.157.221.52, 52.28.184.187, 52.28.212.16, 52.29.176.99, 52.57.230.214, 54.76.184.103, 52.210.122.50, 52.208.95.174
+```
+
+### Australia
+
+```text
+52.64.84.177, 52.64.111.197, 54.153.131.0, 13.210.52.131, 13.55.232.24, 13.54.254.182, 52.62.91.160, 52.63.36.78, 52.64.120.184, 54.66.205.24, 54.79.46.4
+```
+
+## Inbound Calls
+
+IP addresses related to inbound calls to Auth0 may be variable due to the lack of fixed IP addresses on the load balancers. In this case firewall rules should operate on the name of the service (e.g. `.auth0.com`).
diff --git a/articles/guides/login/_includes/_centralized_webapp.md b/articles/guides/login/_includes/_centralized_webapp.md
index 3c1d2056fd..beb5e5dd35 100644
--- a/articles/guides/login/_includes/_centralized_webapp.md
+++ b/articles/guides/login/_includes/_centralized_webapp.md
@@ -9,7 +9,7 @@ router.get('/callback',
```
## Convert your Code to use Universal Login
-In web applications, you don't need any client-side code to integrate universal login. Your application should perform these steps:
+In web applications, you don't need any client-side code to integrate Universal Login. Your application should perform these steps:
1. When the application needs to authenticate, navigate to a `/login` route in your website. If you were using plain HTML to code the web views, it would be:
@@ -35,6 +35,6 @@ After authentication is done, it will redirect to the `/callback` url as in the
3. Review if you are using any [legacy authentication flow in your application](guides/migration-legacy-flows), and adjust your code accordingly.
-You can find complete examples of implementing universal login in web applications for different technologies in our [Quickstarts](/quickstart/webapp).
+You can find complete examples of implementing Universal Login in web applications for different technologies in our [Quickstarts](/quickstart/webapp).
<%= include('_customizing-login-page') %>
diff --git a/articles/guides/login/_includes/_customizing-login-page.md b/articles/guides/login/_includes/_customizing-login-page.md
index 9980122d8f..92d0bd121b 100644
--- a/articles/guides/login/_includes/_customizing-login-page.md
+++ b/articles/guides/login/_includes/_customizing-login-page.md
@@ -1,16 +1,16 @@
## Customizing the Login Page
-When you integrate universal login in your application, you redirect the user to the `/authorize` endpoint of your Auth0 tenant. If Auth0 needs to authenticate the user, it will show the default login page.
+When you integrate Universal Login in your application, you redirect the user to the `/authorize` endpoint of your Auth0 tenant. If Auth0 needs to authenticate the user, it will show the default login page.
-You can customize the login page in your [Dashboard](${manage_url}/#/login_page) under Hosted Pages, by enabling the **Customize Login Page** toggle.
+You can customize the login page in your [Dashboard](${manage_url}/#/login_settings) under Universal Login, by enabling the **Customize Login Page** toggle.

## Customize Lock in the Login Page
-The default login page for universal login with your tenant is a template that will use [Lock](/libraries/lock) to provide your users with an attractive interface and smooth authentication process. You can look over that template and use it as a starting point if you choose to customize it in any way.
+The default login page for Universal Login with your tenant is a template that will use [Lock](/libraries/lock) to provide your users with an attractive interface and smooth authentication process. You can look over that template and use it as a starting point if you choose to customize it in any way.
-If you want to change any of Lock's [configurable options](/libraries/lock/configuration), you can do so using the editor [Dashboard](${manage_url}/#/login_page) under Hosted Pages. These options can alter the behavior of Lock itself, or the look and feel of the widget using the theming options. See the [configuration documentation](/libraries/lock/configuration) for details on how to customize Lock.
+If you want to change any of Lock's [configurable options](/libraries/lock/configuration), you can do so using the editor [Dashboard](${manage_url}/#/login_settings) under Universal Login. These options can alter the behavior of Lock itself, or the look and feel of the widget using the theming options. See the [configuration documentation](/libraries/lock/configuration) for details on how to customize Lock.
When you're done making changes to the code, click **Save** to persist the changes.
diff --git a/articles/guides/login/migrating-lock-v10-spa.md b/articles/guides/login/migrating-lock-v10-spa.md
index 8d66b3dbef..f24d3acc12 100644
--- a/articles/guides/login/migrating-lock-v10-spa.md
+++ b/articles/guides/login/migrating-lock-v10-spa.md
@@ -1,12 +1,20 @@
---
title: Moving SPAs using Lock to Universal Login
-description: Learn how to migrate from Single Page Applications using Lock to Universal Login
+description: Learn how to migrate from Single-Page Applications using Lock to Universal Login
toc: true
+topics:
+ - lock
+ - migrations
+ - spa
+ - universal-login
+contentType:
+ - how-to
+useCase: migrate
---
# Migrate SPAs using Lock 10+ to Universal Login
-This document explains how to migrate Single Page Applications using [Lock](/libraries/lock) to universal login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
+This document explains how to migrate Single-Page Applications using [Lock](/libraries/lock) to Universal Login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
When you use Lock, your code does basically this:
@@ -54,7 +62,7 @@ function login() {
}
```
-To use **universal login**, you need to use [auth0.js](/libraries/auth0js) to perform the same tasks:
+To use **Universal Login**, you need to use [auth0.js](/libraries/auth0js) to perform the same tasks:
1. Initialize auth0.js, using the same parameters as when initializing Lock:
@@ -99,6 +107,6 @@ function login() {
5. Review if you are using any [legacy authentication flow in your application](guides/migration-legacy-flows), and adjust your code accordingly.
-You can find complete examples of implementing universal login in Single Page Applications for different technologies in our [Quickstarts](/quickstart/spa).
+You can find complete examples of implementing Universal Login in Single-Page Applications for different technologies in our [Quickstarts](/quickstart/spa).
<%= include('_includes/_customizing-login-page') %>
diff --git a/articles/guides/login/migrating-lock-v10-webapp.md b/articles/guides/login/migrating-lock-v10-webapp.md
index 0861c719ee..b2378e8a08 100644
--- a/articles/guides/login/migrating-lock-v10-webapp.md
+++ b/articles/guides/login/migrating-lock-v10-webapp.md
@@ -2,10 +2,18 @@
title: Moving Web Applications using Lock to Universal Login
description: Learn how to migrate from Web Applications using Lock to Universal Login
toc: true
+topics:
+ - lock
+ - migrations
+ - web-apps
+ - universal-login
+contentType:
+ - how-to
+useCase: migrate
---
# Migrate Web Applications using Lock 10+ to Universal Login
-This document explains how to migrate Web Applications using [Lock 10+](/libraries/lock) to universal login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
+This document explains how to migrate Web Applications using [Lock 10+](/libraries/lock) to Universal Login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
When you use Lock in a Web Application, your code does basically this:
diff --git a/articles/guides/login/migrating-lock-v8.md b/articles/guides/login/migrating-lock-v8.md
index dfefdf1e11..62c9674b41 100644
--- a/articles/guides/login/migrating-lock-v8.md
+++ b/articles/guides/login/migrating-lock-v8.md
@@ -2,10 +2,16 @@
title: Moving Applications using Lock 8 to Universal Login
description: Learn how to migrate from Applications using Lock 8 to Universal Login
toc: true
+topics:
+ - lock
+ - migrations
+ - universal-login
+contentType: index
+useCase: migrate
---
# Migrating Applications using Lock 8 to Universal Login
-Lock v8 is very similar to Lock v9 from an API standpoints, so the guides for v9 give you all the information you need to migrate to universal login:
+Lock v8 is very similar to Lock v9 from an API standpoints, so the guides for v9 give you all the information you need to migrate to Universal Login:
- [Migrating Web Applications using Lock 9](/guides/login/migrating-lock-v9-webapp)
diff --git a/articles/guides/login/migrating-lock-v9-spa-popup.md b/articles/guides/login/migrating-lock-v9-spa-popup.md
index cabfc6a8d4..0e4fdeac6d 100644
--- a/articles/guides/login/migrating-lock-v9-spa-popup.md
+++ b/articles/guides/login/migrating-lock-v9-spa-popup.md
@@ -2,12 +2,20 @@
title: Migrate SPAs Using Lock 9 Popup Mode to Universal Login
description: Learn how to Migrate SPAs Using Lock 9 Popup Mode to Universal Login
toc: true
+topics:
+ - lock
+ - migrations
+ - spa
+ - universal-login
+contentType:
+ - how-to
+useCase: migrate
---
# Migrate SPAs Using Lock 9 Popup Mode to Universal Login
-This document explains how to migrate Web Applications using [Lock](/libraries/lock) to universal login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
+This document explains how to migrate Web Applications using [Lock](/libraries/lock) to Universal Login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
-When you use 'popup mode' in Lock 9 applications, the entire authentication flow happens in a web page, without any kind of redirection. That will change when you use universal login.
+When you use 'popup mode' in Lock 9 applications, the entire authentication flow happens in a web page, without any kind of redirection. That will change when you use Universal Login.
1. Initialize Lock:
@@ -40,7 +48,7 @@ function login()
}
```
-To use **universal login**, you need to use [auth0.js](/libraries/auth0js) to manage the authentication flow:
+To use **Universal Login**, you need to use [auth0.js](/libraries/auth0js) to manage the authentication flow:
1. Initialize auth0.js, using the same parameters as when initializing Lock and also including the ones you use when you call lock.show().
@@ -76,6 +84,6 @@ webAuth.parseHash(function(err, authResult) {
4. Review if you are using any [legacy authentication flow in your application](guides/migration-legacy-flows), and adjust your code accordingly.
-You can find complete examples of implementing universal login in Single Page Applications for different technologies in our [Quickstarts](/quickstart/spa).
+You can find complete examples of implementing Universal Login in Single-Page Applications for different technologies in our [Quickstarts](/quickstart/spa).
<%= include('_includes/_customizing-login-page') %>
diff --git a/articles/guides/login/migrating-lock-v9-spa.md b/articles/guides/login/migrating-lock-v9-spa.md
index fa0c8a26a5..ced825aa61 100644
--- a/articles/guides/login/migrating-lock-v9-spa.md
+++ b/articles/guides/login/migrating-lock-v9-spa.md
@@ -2,10 +2,18 @@
title: Moving Web Applications using Lock to Universal Login
description: Learn how to migrate from Web Applications using Lock to Universal Login
toc: true
+topics:
+ - lock
+ - migrations
+ - spa
+ - universal-login
+contentType:
+ - how-to
+useCase: migrate
---
-# Migrate Single Page Applications using Lock 9 to Universal Login
+# Migrate Single-Page Applications using Lock 9 to Universal Login
-This document explains how to migrate Web Applications using [Lock](/libraries/lock) to universal login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
+This document explains how to migrate Web Applications using [Lock](/libraries/lock) to Universal Login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
When you use Lock v9 in a Web Application, your code does basically this:
@@ -47,7 +55,7 @@ function login() {
}
```
-To use **universal login**, you need to use [auth0.js](/libraries/auth0js) to manage the authentication flow:
+To use **Universal Login**, you need to use [auth0.js](/libraries/auth0js) to manage the authentication flow:
1. Initialize auth0.js, using the same parameters as when initializing Lock and also including the ones you use when you call lock.show():
@@ -83,6 +91,6 @@ function login() {
4. Review if you are using any [legacy authentication flow in your application](guides/migration-legacy-flows), and adjust your code accordingly.
-You can find complete examples of implementing universal login in Single Page Applications for different technologies in our [Quickstarts](/quickstart/spa).
+You can find complete examples of implementing Universal Login in Single-Page Applications for different technologies in our [Quickstarts](/quickstart/spa).
<%= include('_includes/_customizing-login-page') %>
diff --git a/articles/guides/login/migrating-lock-v9-webapp.md b/articles/guides/login/migrating-lock-v9-webapp.md
index 7b97086a39..1df0f0a1e4 100644
--- a/articles/guides/login/migrating-lock-v9-webapp.md
+++ b/articles/guides/login/migrating-lock-v9-webapp.md
@@ -2,10 +2,18 @@
title: Moving Web Applications using Lock to Universal Login
description: Learn how to migrate from Web Applications using Lock to Universal Login
toc: true
+topics:
+ - lock
+ - migrations
+ - web-apps
+ - universal-login
+contentType:
+ - how-to
+useCase: migrate
---
# Migrate Web Applications using Lock 9 to Universal Login
-This document explains how to migrate Web Applications using Lock to universal login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
+This document explains how to migrate Web Applications using Lock to Universal Login. For other migration scenarios see [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal).
When you use Lock v9 in a Web Application, your code does basically this:
diff --git a/articles/guides/login/migration-embedded-universal.md b/articles/guides/login/migration-embedded-universal.md
index fb5bd75a5e..6bd0804496 100644
--- a/articles/guides/login/migration-embedded-universal.md
+++ b/articles/guides/login/migration-embedded-universal.md
@@ -1,20 +1,28 @@
---
title: Migrating from Embedded to Universal Login
description: Learn how to migrate from Embedded Login using Lock to Universal Login
+topics:
+ - lock
+ - migrations
+ - universal-login
+ - embedded-login
+contentType:
+ - index
+useCase: migrate
---
# Migrating to Universal Login
-When you integrate Auth0 in our applications, you have to decide whether you will use embedded or universal login.
+When you integrate Auth0 in our applications, you have to decide whether you will use embedded or Universal Login.
- With embedded login the login dialog is hosted in your application. You can use [Lock](/libraries/lock) or create your own UI and use [auth0.js](/libraries/auth0js).
-- With universal login, you redirect to an Auth0-hosted [login page](/hosted-pages/login) where the authentication flow is performed.
+- With Universal Login, you redirect to an Auth0-hosted [login page](/universal-login) where the authentication flow is performed.
-Universal login has several advantages over embedded login. For a detailed analysis refer to [Centralized vs Embedded Login](/guides/login/universal-vs-embedded).
+Universal Login has several advantages over embedded login. For a detailed analysis refer to [Centralized vs Embedded Login](/guides/login/universal-vs-embedded).
-We put together a set of articles to help you migrate to universal login in different scenarios.
+We put together a set of articles to help you migrate to Universal Login in different scenarios.
-You can also find how to implement universal login in multiple technology stacks using [our Quickstarts](/quickstart).
+You can also find how to implement Universal Login in multiple technology stacks using [our Quickstarts](/quickstart).
## Migration Guides per Application Type
diff --git a/articles/guides/login/migration-sso.md b/articles/guides/login/migration-sso.md
index d9b23551a1..b309d94aa7 100644
--- a/articles/guides/login/migration-sso.md
+++ b/articles/guides/login/migration-sso.md
@@ -1,19 +1,28 @@
---
-title: Migration in Embedded Login Scenarios with SSO
-description: Learn how to migrate from old versions of Lock/Auth0.js when your application uses embedded login and requires SSO.
+title: Migration in Embedded Login Scenarios with Single Sign-On
+description: Learn how to migrate from old versions of Lock/Auth0.js when your application uses embedded login and requires Single Sign-on (SSO).
+topics:
+ - lock
+ - migrations
+ - sso
+ - embedded-login
+contentType:
+ - concept
+ - index
+useCase: migrate
---
-# Migration in Embedded Login Scenarios with SSO
+# Migration in Embedded Login Scenarios with Single Sign-On
-Migration from legacy versions of Lock and Auth0.js is required. For Single Sign On (SSO) scenarios, it will imply moving to [Universal Login](/hosted-pages/login) in most cases.
+Migration from legacy versions of Lock and Auth0.js is required. For Single Sign-on (SSO) scenarios, it will imply moving to [Universal Login](/universal-login) in most cases.
-## Single Page Apps
+## Single-Page Apps
-Single Page Applications (SPAs) with embedded login can only achieve SSO if they are on the same top-level domain. If SPAs with embedded login which are on different domains require SSO, the websites will need to [migrate to Universal Login](/guides/login/migration-embedded-universal).
+Single-Page Applications (SPAs) with embedded login can only achieve SSO if they are on the same top-level domain. If SPAs with embedded login which are on different domains require SSO, the websites will need to [migrate to Universal Login](/guides/login/migration-embedded-universal).
SSO works by having Auth0 set a cookie that identifies the session in the Auth0 server for a specific domain.
-In order to make embedded login work properly, you need to set up a [custom domain](/custom-domains) that matches your website's top level domain, so as to avoid [cross-origin authentication issues](/cross-origin-authentication#limitations-of-cross-origin-authentication).
+In order to make embedded login work properly, you need to set up a [custom domain](/custom-domains) that matches your website's top level domain, so as to avoid [cross-origin authentication issues](/cross-origin-authentication#limitations).
If two applications using embedded login are sitting on different top-level domains, they would need to point to two different custom domains in order implement embedded login properly. If they are on different domains, those domains cannot share the same SSO cookie, so you can’t implement SSO across those sites.
@@ -23,4 +32,4 @@ Web Applications using embedded login that require SSO need to [migrate to Unive
The proper way of implementing embedded login for web applications is by creating a custom form that POSTs credentials to the web application. The web application then validates them with Auth0 using the [/oauth/token endpoint](/api-auth/tutorials/password-grant).
-This approach does not allow for the creation of an SSO session, as the Auth0 server cannot set a cookie in the end-user’s browser. It also prevents Auth0 from performing [Anomaly Detection](/anomaly-detection#restrictions-regarding-brute-force-protection).
+This approach does not allow for the creation of an SSO session, as the Auth0 server cannot set a cookie in the end-user’s browser. It also prevents Auth0 from performing [Anomaly Detection](/anomaly-detection).
diff --git a/articles/guides/login/universal-vs-embedded.md b/articles/guides/login/universal-vs-embedded.md
index c37a39ec4f..73fe301b7c 100644
--- a/articles/guides/login/universal-vs-embedded.md
+++ b/articles/guides/login/universal-vs-embedded.md
@@ -2,12 +2,21 @@
title: Universal vs Embedded Login
description: Read about the differences between Universal and Embedded login
toc: true
+topics:
+ - universal-login
+ - embedded-login
+ - migrations
+contentType:
+ - concept
+useCase:
+ - strategize
+ - development
---
# Universal vs Embedded Login
When you design the authentication experience for your application, you have to choose whether the login flow will use **universal** or **embedded** login.
-With universal login, when the users try to log in they are redirected to a central domain, through which authentication is performed, and then they are redirected back to the app. An example is Google Apps. No matter which service you are trying to access (gmail, google calendar, google docs, etc) if you are not logged in you are redirected to `https://accounts.google.com` and once you successfully log in you are redirected back to the calling app.
+With Universal Login, when the users try to log in they are redirected to a central domain, through which authentication is performed, and then they are redirected back to the app. An example is G Suite. No matter which service you are trying to access (gmail, google calendar, google docs, etc) if you are not logged in you are redirected to `https://accounts.google.com` and once you successfully log in you are redirected back to the calling app.

@@ -19,23 +28,23 @@ In this article, we will evaluate the pros and cons of these two options and see
## Pros and cons
-- **Single Sign-On (SSO)**: If you are working with mobile apps you cannot have SSO unless you use universal login. With web apps you can, although the most secure way is to use a central service so the cookies are from the same origin. With embedded login, you'd have to collect the user credentials in an application served from one origin and then send them to another origin, which can present certain security vulnerabilities, including the possibility of a phishing attack (see [Embedded Login with Auth0 > Security risks](#security-risks) for more info). There are workarounds you could use, like third-party cookies, but the most secure option for SSO, and logins in general, is using a central service.
+- **Single Sign-on (SSO)**: If you are working with mobile apps you cannot have SSO unless you use Universal Login. With web apps you can, although the most secure way is to use a central service so the cookies are from the same origin. With embedded login, you'd have to collect the user credentials in an application served from one origin and then send them to another origin, which can present certain security vulnerabilities, including the possibility of a phishing attack (see [Embedded Login with Auth0 > Security risks](#security-risks) for more info). There are workarounds you could use, like third-party cookies, but the most secure option for SSO, and logins in general, is using a central service.
-- **Consistency and Maintenance**: With embedded login, if you have more than one app, you will have to implement more than one login page. You will also have to maintain and manage these pages. Besides the extra effort it can also introduce inconsistencies which results in bad UX. Furthermore, with embedded login you would have to manage the dangers of cross-origin attack vectors. On the other hand, if you are using universal login, then your Authorization Server (the domain that logs the users in) owns all the login pages which makes the management easier and the pages more consistent and secure. You could also use a single login page among your apps, a process that creates an impression that users are logging into a centralized system, rather than an individual app. In the following diagram you can see an example of how the universal and embedded logins look. The reason why the universal login offers a more consistent and thus superior use experience is evident.
+- **Consistency and Maintenance**: With embedded login, if you have more than one app, you will have to implement more than one login page. You will also have to maintain and manage these pages. Besides the extra effort it can also introduce inconsistencies which results in bad UX. Furthermore, with embedded login you would have to manage the dangers of cross-origin attack vectors. On the other hand, if you are using Universal Login, then your Authorization Server (the domain that logs the users in) owns all the login pages which makes the management easier and the pages more consistent and secure. You could also use a single login page among your apps, a process that creates an impression that users are logging into a centralized system, rather than an individual app. In the following diagram you can see an example of how the universal and embedded logins look. The reason why the Universal Login offers a more consistent and thus superior use experience is evident.

-- **Central Features Management**: When you use universal login with Auth0, you can turn on and off features across all your apps, using the Dashboard. An example is [Multifactor Authentication](/multifactor-authentication) which you can enable using the toggles located at the [Dashboard > Multifactor Auth](${manage_url}/#/guardian) page. These changes will be automatically available to all your registered apps.
+- **Central Features Management**: When you use Universal Login with Auth0, you can turn on and off features across all your apps, using the Dashboard. An example is [Multi-factor Authentication](/mfa) which you can enable using the toggles located at the [Dashboard > Multi-factor Auth](${manage_url}/#/mfa) page. These changes will be automatically available to all your registered apps.
- **User Experience**: In the past, an argument could be made that the user experience with embedded login was better because it did not require redirecting users to another subdomain. However, users are getting increasingly familiar with the process of being redirected to another subdomain to log in. As a result, they don't find the process disruptive to their experience. Think about this, when you try to access your Gmail, if you are not logged in, you get redirected to the Google Accounts subdomain in order to log in. Do you get frustrated with that? You probably don't even notice it.
-- **Mobile Apps & Security**: According to the [Best Current Practice for OAuth 2.0 for Native Apps Request For Comments](https://www.rfc-editor.org/rfc/rfc8252.txt), only external user agents (such as the browser) should be used by native applications for authentication flows. Using the browser to make native app authorization requests results in better security and it gives users the confidence that they are entering credentials in the right domain. It also enables use of the user's current authentication state, making single sign-on possible. Embedded user agents are deemed unsafe for third parties and should not be implemented (see [Embedded Login with Auth0 > Security risks](#security-risks) for more info). With native login a malicious app could try and phish users for username/password or tokens. Also, if your mobile apps use native login, then your users have to enter their credentials for each of your apps, hence SSO is not possible.
+- **Mobile Apps & Security**: According to the [Best Current Practice for OAuth 2.0 for Native Apps Request For Comments](https://www.rfc-editor.org/rfc/rfc8252.txt), only external user agents (such as the browser) should be used by native applications for authentication flows. Using the browser to make native app authorization requests results in better security and it gives users the confidence that they are entering credentials in the right domain. It also enables use of the user's current authentication state, making Single Sign-on (SSO) possible. Embedded user agents are deemed unsafe for third parties and should not be implemented (see [Embedded Login with Auth0 > Security risks](#security-risks) for more info). With native login a malicious app could try and phish users for username/password or tokens. Also, if your mobile apps use native login, then your users have to enter their credentials for each of your apps, hence SSO is not possible.
-## Universal login with Auth0
+## Universal Login with Auth0
-For most situations, we recommend using a a universal login strategy, where Auth0 will show a [login page](/hosted-pages/login) if authentication is required. You can customize your login page using the [Dashboard](${manage_url}/#/login_page).
+For most situations, we recommend using a Universal Login strategy, where Auth0 will show a [login page](/universal-login) if authentication is required. You can customize your login page using the [Dashboard](${manage_url}/#/login_page).
-You can use **Auth0's Custom Domains** in order to persist the same domain across the login page and the app. This way the redirect to the login page will be transparent to your users since the domain will not change. For more details refer to [Custom Domains Overview](/custom-domains).
+You can use **Auth0's Custom Domains** in order to persist the same domain across the login page and the app. This way the redirect to the login page will be transparent to your users since the domain will not change. For more details, see [Custom Domains](/custom-domains).
Whenever your app triggers an authentication request, the user will be redirected to the login page in order to authenticate. This will create a cookie. In future authentication requests, Auth0 will check for this cookie, and if it is present the user will not be redirected to the login page. They will see the page only when they need to actually log in. This is the easiest way to implement SSO.
@@ -45,36 +54,35 @@ Note that if the incoming authentication request uses an external identity provi
You can deploy your custom login page from an external repository, like [GitHub](/extensions/github-deploy#deploy-hosted-pages), [Bitbucket](/extensions/bitbucket-deploy#deploy-hosted-pages), [GitLab](/extensions/gitlab-deploy#deploy-hosted-pages), or [Visual Studio Team Services](/extensions/visual-studio-team-services-deploy#deployment).
:::
-Our recommendation is to use universal login when you use Auth0. The first and foremost reason is security. Using Auth0 hosted pages instead of hosting them externally provides seamless CSRF protection. This helps prevent third-party impersonation or the hijacking of sessions.
+Our recommendation is to use Universal Login when you use Auth0. The first and foremost reason is security. Using Auth0 Universal Login instead of embedding login in your application provides seamless CSRF protection. This helps prevent third-party impersonation or the hijacking of sessions.
## Embedded login with Auth0
Embedded logins in web apps with Auth0 use [Cross-Origin Authentication](/cross-origin-authentication). This uses [third-party cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Third-party_cookies) to allow for secure authentication transactions across different origins. This does not apply to native applications since they use the standard OAuth 2.0 token endpoint.
::: note
-Cross-origin authentication is only necessary when authenticating against a directory using a username and password. Social identity providers and enterprise federation use a different mechanism, redirecting via standard protocols like OpenID Connect and SAML.
+Cross-origin authentication is not recommended and is only necessary when authenticating against a directory using a username and password. Social IdPs and enterprise federation use a different mechanism, redirecting via standard protocols like OpenID Connect (OIDC) and SAML. Additionally, cross-origin authentication is only applicable to embedded login on the web (using Lock or auth0.js). Native applications using embedded login make use of the standard OAuth 2.0 token endpoint.
:::
-In addition, if you have not enabled [Custom Domain Names](/custom-domains) the end user must have a browser that supports third-party cookies, otherwise, in some browsers, cross-origin authentication will fail. For more information refer to [Limitations of Cross-Origin Authentication](/cross-origin-authentication).
+In addition, if you have not enabled [custom domains](/custom-domains), the end user must have a browser that supports third-party cookies. Otherwise, in some browsers, cross-origin authentication will fail. For more information, see [Cross-Origin Authentication](/cross-origin-authentication#limitations). This limitation applies to both traditional username/password database connections as well as to passwordless database connections.
+
### Security risks
-Universal login is more secure than embedded login. Authentication takes place over the same domain, eliminating cross-origin requests. Cross-origin authentication is inherently more dangerous. Collecting user credentials in an application served from one origin and then sending them to another origin can present certain security vulnerabilities. [Phishing attacks](https://auth0.com/blog/all-you-need-to-know-about-the-google-docs-phishing-attack/) are more likely, as are [man-in-the-middle attacks](/security/common-threats#man-in-the-middle-mitm-attacks). Universal login does not send information between origins, thereby negating cross-origin concerns.
+Universal Login is more secure than embedded login. Authentication takes place over the same domain, eliminating cross-origin requests. Cross-origin authentication is inherently more dangerous. Collecting user credentials in an application served from one origin and then sending them to another origin can present certain security vulnerabilities. Phishing attacks are more likely, as are [man-in-the-middle attacks](/security/common-threats#man-in-the-middle-mitm-attacks). Universal Login does not send information between origins, thereby negating cross-origin concerns.
Embedded user agents are unsafe for third parties, including the authorization server itself. If an embedded login is used, the app has access to both the authorization grant and the user's authentication credentials. As a consequence, this data is left vulnerable to recording or malicious use. Even if the app is trusted, allowing it to access the authorization grant as well as the user's **full credentials** is unnecessary. This violates the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) and increases the potential for attack.
:::note
-As a matter of fact, Google no longer supports an embedded approach when implementing OAuth. For more information on this, refer to [Google Blocks OAuth Requests Made via embedded browsers](https://auth0.com/blog/google-blocks-oauth-requests-from-embedded-browsers/).
+Google no longer supports an embedded approach when implementing OAuth.
:::
-Furthermore, according to the [Internet Engineering Task Force (IETF)](https://www.ietf.org/), authorization requests from native apps should only be made through external user agents, primarily the user's browser. Using the browser to make native app authorization requests results in better security. When embedded agents are used, the app has access to the OAuth authorization grant as well as the user's credentials, leaving this data vulnerable to recording or malicious use. For more info refer to [OAuth 2.0 Best Practices for Native Apps](https://auth0.com/blog/oauth-2-best-practices-for-native-apps/).
+Furthermore, according to the [Internet Engineering Task Force (IETF)](https://www.ietf.org/), authorization requests from native apps should only be made through external user agents, primarily the user's browser. Using the browser to make native app authorization requests results in better security. When embedded agents are used, the app has access to the OAuth authorization grant as well as the user's credentials, leaving this data vulnerable to recording or malicious use.
## Keep reading
:::next-steps
- [Migrating from Embedded to Universal Login](/guides/login/migration-embedded-universal)
- [Browser-Based vs. Native Login Flows on Mobile Devices](/design/browser-based-vs-native-experience-on-mobile)
-- [Authentication Provider Best Practices: Universal Login](https://auth0.com/blog/authentication-provider-best-practices-centralized-login/)
-- [OAuth 2.0 Best Practices for Native Apps](https://auth0.com/blog/oauth-2-best-practices-for-native-apps/)
- [Modernizing OAuth interactions in Native Apps for Better Usability and Security](https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html)
:::
diff --git a/articles/guides/migration-legacy-flows.md b/articles/guides/migration-legacy-flows.md
index c95b872489..ba6f220bab 100644
--- a/articles/guides/migration-legacy-flows.md
+++ b/articles/guides/migration-legacy-flows.md
@@ -3,6 +3,16 @@ section: libraries
title: Migrating from Legacy Authentication Flows
description: How to migrate from Legacy Authentication Flows
toc: true
+topics:
+ - migrations
+ - lock
+ - auth0js
+ - tokens
+ - user-profiles
+contentType:
+ - how-to
+ - concept
+useCase: migrate
---
# Migrating from Legacy Authentication Flows
@@ -10,11 +20,11 @@ When using Lock versions below 11 and Auth0.js version below 9, you could use le
## Renewing Tokens
-Legacy applications used [Refresh Tokens](/tokens/refresh-token) and the `refreshToken()` function as a way to get new tokens upon expiration (an example of this is below).
+Legacy applications used Refresh Tokens and the `refreshToken()` function as a way to get new tokens upon expiration (an example of this is below).
```js
function renewToken() {
- // Assumes the refresh_token is stored in localStorage
+ // Assumes the Refresh Token is stored in localStorage
refresh_token = localStorage.getItem('refresh_token');
auth0.refreshToken(refresh_token, function (err, delegationResult) {
if (!err)
@@ -22,9 +32,9 @@ function renewToken() {
var expires_at = JSON.stringify(
delegationResult.expires_in* 1000 + new Date().getTime())
;
- // Assumes you want to keep the time the token will expire
- // and the id_token in localStorage
- localStorage.setItem('expires_at', expires_at);
+ // Assumes you want to keep the time the token will expire
+ // and the ID Token in localStorage
+ localStorage.setItem('expires_at', expires_at);
localStorage.setItem('id_token', delegationResult.id_token);
}
);
@@ -52,14 +62,14 @@ Check the [Silent Authentication documentation](/api-auth/tutorials/silent-authe
## Calling APIs
-Legacy applications used an [ID Token](/tokens/id-token) to invoke APIs. This [is a bad practice](/api-auth/why-use-access-tokens-to-secure-apis) and we recommend you to start using [Access Tokens](/tokens/access-token).
+Legacy applications used an [ID Token](/tokens/concepts/id-tokens) to invoke APIs. This is a bad practice, and we recommend that you only use [Access Tokens](/tokens/concepts/access-tokens).
To call an API, you will need to specify the API identifier as the `audience` parameter when initializing auth0.js or Lock.
```js
var lock = new Auth0Lock('${account.clientId}', '${account.namespace}', {
auth: {
- audience: 'https::/mydomain.com/api',
+ audience: 'https://mydomain.com/api',
}
});
```
@@ -68,7 +78,9 @@ If you specify an audience, then the OIDC flow will be triggered and the user pr
You can check the **Calling an API** section of our [SPA Quickstarts](/quickstart/backend) for more information on how to call APIs from SPAs. You will also need to migrate your backend API implementation to use Access Tokens. You can look at our [API Quickstarts](/quickstart/backend) for instructions on how to do this.
-## User Profiles
+## User Profiles
+
+The legacy authentication flows that allow ID Tokens and the `/userinfo` endpoint to include the complete user profile are being deprecated. Make sure the `Legacy User Profile` toggle is turned off after completing the migration to the new OIDC-conformant APIs.
When using the legacy authentication flows, the entire user profile is returned in ID Tokens and from `/userinfo`, as demonstrated below.
@@ -114,21 +126,21 @@ The new user profile conforms to the OIDC specification, which allows for certai
}
```
-The contents will vary depending on which [scopes](/scopes) are requested. You will need to adjust the scopes you request when configuring Auth0.js or Lock so all the claims you need are available in your application. Note that you can add custom claims to return whatever data you want (for example, user metadata), as described in [this example](/scopes/current#example-add-custom-claims).
+The contents will vary depending on which [scopes](/scopes) are requested. You will need to adjust the scopes you request when configuring Auth0.js or Lock so all the claims you need are available in your application. Note that you can add custom claims to return whatever data you want (for example, user metadata), as described in [this example](/scopes/current/sample-use-cases#add-custom-claims-to-a-token).
Another approach to get the full user profile is to use the [Management API](/api/management/v2) (instead of getting the profile through the authentication flow) as described in the next section.
## User Profile with Management API
-In the legacy flows, the [Management API](/api/management/v2) supported authentication with an `id_token`. This approach has been deprecated, and now you need to call it with an `access_token`.
+In the legacy flows, the [Management API](/api/management/v2) supported authentication with an ID Token. This approach has been deprecated, and now you need to call it with an Access Token.
-To get an `access_token`, you need to ask Auth0 for one using the `https://${account.namespace}/api/v2/` audience. Auth0 does not currently support specifying two audiences when authenticating, so you will need to still use your application's API audience when initializing Lock or auth0.js. Once the user is authenticated, you can use `checkSession` to retrieve a Management API `access_token`, and then call the [getUser() endpoint](/api/management/v2#!/Users/get_users_by_id).
+To get an Access Token, you need to ask Auth0 for one using the `https://${account.namespace}/api/v2/` audience. Auth0 does not currently support specifying two audiences when authenticating, so you will need to still use your application's API audience when initializing Lock or auth0.js. Once the user is authenticated, you can use `checkSession` to retrieve a Management API `access_token`, and then call the [getUser() endpoint](/api/management/v2#!/Users/get_users_by_id).
```js
function getUserUsingManagementApi() {
webAuth.checkSession(
{
- audience: `https://${account.namespace}/api/v2/˜`,
+ audience: `https://${account.namespace}/api/v2/`,
scope: 'read:current_user'
},
function(err, result) {
diff --git a/articles/hooks/_includes/_access_hook_secrets.md b/articles/hooks/_includes/_access_hook_secrets.md
new file mode 100644
index 0000000000..f97a1aa5fb
--- /dev/null
+++ b/articles/hooks/_includes/_access_hook_secrets.md
@@ -0,0 +1,3 @@
+::: note
+To access a configured Hook Secret from within a Hook, use `context.webtask.secrets.SECRET_NAME`.
+:::
\ No newline at end of file
diff --git a/articles/hooks/_includes/_default_hook_enable_behavior.md b/articles/hooks/_includes/_default_hook_enable_behavior.md
new file mode 100644
index 0000000000..fd1cac9b99
--- /dev/null
+++ b/articles/hooks/_includes/_default_hook_enable_behavior.md
@@ -0,0 +1,3 @@
+::: warning
+When creating new Hooks, Auth0 automatically enables the first Hook you create for an extensibility point. Any subsequent Hooks you create for that extensibility point are automatically disabled, so you must explicitly enable them.
+:::
\ No newline at end of file
diff --git a/articles/hooks/_includes/_handle_rate_limits.md b/articles/hooks/_includes/_handle_rate_limits.md
new file mode 100644
index 0000000000..ec53a8e291
--- /dev/null
+++ b/articles/hooks/_includes/_handle_rate_limits.md
@@ -0,0 +1,5 @@
+::: panel Handle Rate Limits when calling Auth0 APIs from within Hooks
+If you call Auth0 APIs from within a Hook's script, you will need to handle rate limits. To do so, check the `X-RateLimit-Remaining` header and act appropriately when the number returned nears 0.
+
+Additionally, add logic to handle cases in which you exceed the provided rate limits and receive the `429` HTTP Status Code (`Too Many Requests`). In this case, if a re-try is needed, it is best to allow for a back-off to avoid going into an infinite re-try loop. To learn more about rate limits, see [Rate Limit Policy For Auth0 APIs](/policies/rate-limits).
+:::
\ No newline at end of file
diff --git a/articles/hooks/_includes/_hook_enabled_limit.md b/articles/hooks/_includes/_hook_enabled_limit.md
new file mode 100644
index 0000000000..f88e9902b3
--- /dev/null
+++ b/articles/hooks/_includes/_hook_enabled_limit.md
@@ -0,0 +1,3 @@
+::: warning
+Although you may create multiple Hooks for any given extensibility point, each extensibility point may have only **one** **enabled** Hook at a time.
+:::
\ No newline at end of file
diff --git a/articles/hooks/_includes/_hook_secrets_limit.md b/articles/hooks/_includes/_hook_secrets_limit.md
new file mode 100644
index 0000000000..67d2753477
--- /dev/null
+++ b/articles/hooks/_includes/_hook_secrets_limit.md
@@ -0,0 +1,3 @@
+::: note
+You may create up to 20 secrets for any given Hook.
+:::
\ No newline at end of file
diff --git a/articles/hooks/_includes/_test_runner_save_warning.md b/articles/hooks/_includes/_test_runner_save_warning.md
new file mode 100644
index 0000000000..101c626f77
--- /dev/null
+++ b/articles/hooks/_includes/_test_runner_save_warning.md
@@ -0,0 +1,3 @@
+::: warning
+Executing the code using the Runner requires a save, which means that the original code will be overwritten.
+:::
\ No newline at end of file
diff --git a/articles/hooks/cli/create-delete.md b/articles/hooks/cli/create-delete.md
deleted file mode 100644
index 31d2111d15..0000000000
--- a/articles/hooks/cli/create-delete.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-description: How to create/delete Hooks using the Auth0 Command-Line Interfance
-beta: true
----
-
-# Create/Delete Hooks Using the Auth0 Command-Line Interface
-
-::: note
-The Auth0 CLI examples use `auth0-profile` as the name of the profile. This is the same profile name used when installing `wt-cli`, and you can obtain it from *Step 2* of the instructions set located on [Auth0 Management Dashboard's Webtask page](${manage_url}/#/account/webtasks).
-:::
-
-Using the Auth0 CLI, you can create new Hooks, as well as manage or delete existing Hooks. You can also gather real-time data about your Hooks.
-
-## Create a New Hook
-
-Rather than beginning from scratch, you can scaffold the sample code for an Auth0 hook.
-
-`auth0 scaffold -t pre-user-registration > file.js`
-
-Create the hook:
-
-`auth0 create -t pre-user-registration --name my-extension-1 -p auth0-default file.js`
-
-### Provision Secrets to New Hooks
-
-Optionally, you can add provision secrets (such as Twilio Keys or database connection strings) to your new Hook by adding `--secret KEY=VALUE` to your *Create* command. The information you attach will be encrypted, and it can only be decrypted by the Webtask server.
-
-At this point, you have created a new, disabled Hook using the `pre-user-registration` [extensibility point](/hooks/extensibility-points). You can repeat this process and create Hooks for any of the other extensibility points.
-
-## Delete an Existing Hook
-
-If you need to delete an existing Hook, you can do so using the following command:
-
-`auth0 rm my-extension-1 -p auth0-default`
\ No newline at end of file
diff --git a/articles/hooks/cli/edit.md b/articles/hooks/cli/edit.md
deleted file mode 100644
index 5ed62216c7..0000000000
--- a/articles/hooks/cli/edit.md
+++ /dev/null
@@ -1,50 +0,0 @@
----
-description: How to edit Hooks using the Auth0 Command-Line Interfance
-beta: true
----
-
-# Edit Existing Hooks Using the Auth0 Command-Line Interface
-
-::: note
-All of the examples on this page use `auth0-profile` as the name of the profile. This is the same profile name used when installing `wt-cli` and can be obtained from *Step 2* of the instructions set located on [Auth0 Management Dashboard's Webtask page](${manage_url}/#/account/webtasks).
-:::
-
-You can edit the code of your Hook using the [Webtask Editor](https://webtask.io/docs/editor). The following command will open up the code for your Hook in the Webtask Editor window:
-
- `auth0 edit my-extension-1`
-
- 
-
-If the CLI cannot open the Editor window automatically, you can copy and paste the provided link into your web browser.
-
-::: note
-Please see the [Webtask docs](https://webtask.io/docs/editor) for detailed information on using the Webtask Editor.
-:::
-
-## Test Your Hook
-
-The Webtask Editor allows you to test your Hook using the Runner. By default, the Runner is hidden until you choose to display it by clicking its icon in the top left of the Editor.
-
-
-
-The Runner allows you to simulate an Auth0 call to your Hook and provides the basic parameters needed to complete the call. You can edit the provided schema as necessary.
-
-
-
-When you're ready, click **Run** to proceed. You will be presented with the results of the call.
-
-
-
-If you run multiple tests, the Runner keeps track of the calls you've made in its *History* section. For each result, you can see specific details about the call by clicking **>** to the right of the call result.
-
-
-
-:::panel Test Runner Schema
-If you created your Hook early on during the beta testing period, your Webtask Editor/Test Runner window might not populate with the schema required to successfully use the Test Runner. If that is the case, you'll need to save the Hook's code, delete the Hook, and create a new Hook using your existing code.
-:::
-
-## Manipulate Secrets
-
-If you [provisioned a secret to your Hook](/hooks/cli/create-delete#provision-secrets-to-new-hooks) during creation, you can manipulate it by clicking on the **wrench** at the top left of the Webtask Editor window and selecting **Secrets** from the dropdown menu.
-
- 
\ No newline at end of file
diff --git a/articles/hooks/cli/enable-disable.md b/articles/hooks/cli/enable-disable.md
deleted file mode 100644
index 2229fb58a6..0000000000
--- a/articles/hooks/cli/enable-disable.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-description: How to enable/disable Hooks using the Auth0 Command-Line Interfance
-beta: true
----
-
-# Enable or Disable Existing Hooks Using the Auth0 Command-Line Interface
-
-::: note
-All of the examples on this page use `auth0-profile` as the name of the profile. This is the same profile name used when installing `wt-cli` and can be obtained from *Step 2* of the instructions set located on [Auth0 Management Dashboard's Webtask page](${manage_url}/#/account/webtasks).
-:::
-
-For each extensibility point, you may have either no associated Hooks enabled or **one** associated Hook enabled.
-
-By default, the Auth0 CLI creates new Hooks in a disabled state.
-
-## Enable Your Hook
-
-The following command enables your Hook:
-
- `auth0 enable my-extension-1 -p auth0-default`
-
-By enabling a given Hook, the Auth0 CLI disables all other Hooks associated with the same extensibility point.
-
-## Disable Your Hook
-
-The following command disables your Hook:
-
- `auth0 disable my-extension-1 -p auth0-default`
\ No newline at end of file
diff --git a/articles/hooks/cli/index.md b/articles/hooks/cli/index.md
deleted file mode 100644
index 65968957b6..0000000000
--- a/articles/hooks/cli/index.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-description: How to use the Command-Line Interface with Hooks
-url: /hooks/cli
-beta: true
----
-
-# Auth0 Command-Line Interface
-
-The Auth0 Command-Line Interface (CLI) allows you to create, edit, enable/disable, and delete Hooks associated with specific extensibility points within the Auth0 platform. You can also use the CLI to identify Hooks and gather real-time logging information.
-
-## Set Up the CLI
-
-You can find instructions for installing and configuring the Webtask CLI in the [Dashboard > Webtask page](${manage_url}/#/account/webtasks).
-
-The `wt-cli` package also includes the `auth0` binary, allowing you to use the Auth0 CLI.
-
-
-
-## Work with Hooks
-
-Once you have installed and set up the CLI, you can use it to create new Hooks and manage/delete existing Hooks. You can also use it to gather real-time log data on your Hooks.
-
-::: note
-The Auth0 CLI examples use `auth0-profile` as the name of the profile. This is the same profile name used when installing `wt-cli`, and you can obtain it from *Step 2* of the instructions set located on [Dashboard > Webtask](${manage_url}/#/account/webtasks).
-:::
-
-* [Create/Delete Hooks](/hooks/cli/create-delete)
-* [Edit Existing Hooks](/hooks/cli/edit)
-* [Enable/Disable Existing Hooks](/hooks/cli/enable-disable)
-* [Identify and Get Log Data from Your Hooks](/hooks/cli/logs)
\ No newline at end of file
diff --git a/articles/hooks/cli/logs.md b/articles/hooks/cli/logs.md
deleted file mode 100644
index 82b6a88c5e..0000000000
--- a/articles/hooks/cli/logs.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-description: How to get Hooks logs using the Auth0 Command-Line Interface
-beta: true
----
-
-# Get Log Information About Hooks Using the Auth0 Command-Line Interface
-
-::: note
-All of the examples on this page use `auth0-profile` as the name of the profile. This is the same profile name used when installing `wt-cli` and can be obtained from *Step 2* of the instructions set located on [Auth0 Management Dashboard's Webtask page](${manage_url}/#/account/webtasks).
-:::
-
-You can use the Auth0 CLI to gather information about your Hooks:
-
-* To get a list of Hooks for a specific extensibility point:
- `auth0 ls -t pre-user-registration -p auth0-default`
-* To get a list of Hooks associated with your Auth0 account:
- `auth0 ls -p auth0-default`
-* To access logs containing real-time data on your Hooks:
- `auth0 logs -p auth0-default`
\ No newline at end of file
diff --git a/articles/hooks/create.md b/articles/hooks/create.md
new file mode 100644
index 0000000000..40d1be3940
--- /dev/null
+++ b/articles/hooks/create.md
@@ -0,0 +1,90 @@
+---
+title: Create Hooks
+description: Learn how to create Hooks using the Dashboard and Management API. Hooks may also be imported and exported using the Auth0 Deploy Command-Line Interface (CLI) tool.
+topics:
+ - hooks
+ - dashboard
+ - mgmt-api
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# Create Hooks
+
+You can create multiple Hooks for any given [extensibility point](/hooks/extensibility-points) using the Dashboard or Management API.
+
+Hooks may also be imported and exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
+
+<%= include('./_includes/_hook_enabled_limit') %>
+
+
+
+## Create Hooks using the Dashboard
+
+<%= include('./_includes/_default_hook_enable_behavior') %>
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click **Create a Hook**.
+2. Enter a descriptive name for your Hook, select the extensibility point for which the Hook should execute, and click **Create**.
+3. Locate the section for the extensibility point you selected, and click the pencil icon next to the hook you created.
+4. Update the Hook using the Hook Editor, and click the disk icon to save.
+
+
+
+
+## Create Hooks using the Management API
+
+<%= include('./_includes/_default_hook_enable_behavior') %>
+
+1. Make a `POST` call to the [Create a Hook endpoint](/api/management/v2/#!/Hooks/post_hooks). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `HOOK_NAME`, `HOOK_SCRIPT`, and `EXTENSIBILITY_POINT_NAME` placeholder values with your Management API Access Token, Hook name, Hook script, and extensibility point name, respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/hooks",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"name\": \"HOOK_NAME\", \"script\": \"HOOK_SCRIPT\", \"triggerId\": \"EXTENSIBILITY_POINT_NAME\" }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:hooks`. |
+| `HOOK_NAME` | Name of the hook you would like to create. |
+| `HOOK_SCRIPT` | Script that contains the code for the hook. Should match what you would enter if you were creating a new hook using the Dashboard. |
+| `EXTENSIBILITY_POINT_NAME` | Name of the extensibility point for which the hook should execute. Options include: `credentials-exchange`, `pre-user-registration`, `post-user-registration`, `post-change-password`. To learn more about extensibility points, see [Extensibiity Points](/hooks/extensibility-points). |
+
+
+
+
+
+<%= include('./_includes/_handle_rate_limits') %>
+
+::: note
+Optionally, you can add secrets (such as Twilio Keys or database connection strings) to Hooks. To learn more, see [Hook Secrets](/hooks/secrets).
+:::
+
+### Explore starter code and sample Hook scripts
+
+To explore starter code and sample Hook scripts, see the documentation for your chosen [extensibility point](/hooks/extensibility-points):
+
+* [Client Credentials Exchange](/hooks/extensibility-points/client-credentials-exchange)
+* [Post Change Password](/hooks/extensibility-points/post-change-password)
+* [Post User Registration](/hooks/extensibility-points/post-user-registration)
+* [Pre User Registration](/hooks/extensibility-points/pre-user-registration)
+* [Send Phone Message](/hooks/extensibility-points/send-phone-message)
diff --git a/articles/hooks/dashboard/create-delete.md b/articles/hooks/dashboard/create-delete.md
deleted file mode 100644
index b3106a1c70..0000000000
--- a/articles/hooks/dashboard/create-delete.md
+++ /dev/null
@@ -1,45 +0,0 @@
----
-description: How to create new Hooks using the Management Dashboard
-beta: true
----
-
-# Create a New Hook Using the Dashboard
-
-You can create new Hooks using the Auth0 Management Dashboard.
-
-
-
-## Create a New Hook
-
-1. Navigate to [the Hooks page of the Dashboard](${manage_url}/#/hooks). You can create new Hooks in one of two ways:
-
- * Clicking on the **+ Create New Hook** button at the top right of the Hooks page.
- * Finding the extensibility hook you want to work with and then clicking the **Create New Hook** link below.
-
-2. On the *New Hook* pop-up window, provide the requested information:
-
- 
-
- * **Name**: The name for your new Hook
- * **Hook**: The extensibility point associated with your Hook
-
- Click **Create** to create your Hook.
-
- At this point, you will see your newly-created Hook listed under its associated extensibility point.
-
-:::panel New Hooks
-For any given extensibility point, you may create multiple Hooks. However, you may only have **one** Hook enabled per extensibility point at any given time.
-
-Auth0 automatically enables the first Hook you create for an extensibility point, and any subsequent Hooks for that point are created in a disabled state. As such, you must explicitly activate subsequent Hooks.
-:::
-
-
-
-## Delete an Existing Hook
-
-1. In the Hooks page of the Management Dashboard, find the Hook you want to edit.
-2. Click the **Gear** icon next to your Hook.
-3. Click **Delete**.
-4. Confirm that you want to delete your Hook by clicking **YES, DELETE HOOK**.
-
-
\ No newline at end of file
diff --git a/articles/hooks/dashboard/edit.md b/articles/hooks/dashboard/edit.md
deleted file mode 100644
index b965191d05..0000000000
--- a/articles/hooks/dashboard/edit.md
+++ /dev/null
@@ -1,53 +0,0 @@
----
-description: How to edit Hooks using the Management Dashboard
-beta: true
----
-
-# Edit Existing Hooks Using the Dashboard
-
-You can edit the code for your existing Hook using the [Webtask Editor](https://webtask.io/docs/editor). To open up the Webtask Editor:
-
-1. Navigate to [the Hooks page of the Dashboard](${manage_url}/#/hooks) and find the Hook you want to edit.
-2. Click the **Pencil and Paper** icon to the right of the Hook to open the Webtask Editor.
-
- 
-
-3. Edit your Hook using the Webtask Editor.
-
- 
-
- ::: note
- Please see the [Webtask docs](https://webtask.io/docs/editor) for detailed information on using the Webtask Editor.
- :::
-
-## Test Your Hook
-
-The Webtask Editor allows you to test your Hook using the Runner. By default, the Runner is hidden until you choose to display it by clicking its icon in the top left of the Editor.
-
-
-
-The Runner allows you to simulate an Auth0 call to your Hook and provides the basic parameters needed to complete the call. You can edit the provided schema as necessary.
-
-
-
-When you're ready, click **Run** to proceed. You will be presented with the results of the call.
-
-
-
-If you run multiple tests, the Runner keeps track of the calls you've made in its *History* section. For each result, you can see specific details about the call by clicking **>** to the right of the call result.
-
-
-
-:::panel Test Runner Schema
-If you created your Hook early on during the beta testing period, your Webtask Editor/Test Runner window might not populate with the schema required to successfully use the Test Runner. If that is the case, you'll need to save the Hook's code, delete the Hook, and create a new Hook using your existing code.
-:::
-
-## Rename Your Hook
-
-You can rename your Hook using the Management Dashboard.
-
-1. In [the Hooks page of the Dashboard](${manage_url}/#/hooks), find the Hook you want to edit.
-2. Click the **Gear** icon next to your Hook.
-3. Click **Rename**. You will see a dialog pop up, asking you for the **Current Name** of the Hook, as well as the **New Name** you want to use. Click **Rename** when you have populated both values.
-
-
\ No newline at end of file
diff --git a/articles/hooks/dashboard/enable-disable.md b/articles/hooks/dashboard/enable-disable.md
deleted file mode 100644
index 45bcb33496..0000000000
--- a/articles/hooks/dashboard/enable-disable.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-description: How to enable or disable Hooks using the Management Dashboard
-beta: true
----
-
-# Enable or Disable Existing Hooks Using the Dashboard
-
-You can use the Management Dashboard to enable/disable Hooks. Each extensibility point may be associated with **zero** or **one** active Hook.
-
-::: note
-When creating new Hooks, Auth0 enables your Hook for that extensibility point if there are no other Hooks associated with that point. In any other circumstance, Auth0 does *not* enable your new Hook.
-:::
-
-## Enable a Hook
-
-1. Navigate to [the Hooks page of the Dashboard](${manage_url}/#/hooks) and find the extensibility point for which you want an enabled Hook.
-2. Immediately under the name and description of the extensibility point, click on the dropdown box that lists all of the point's associated Hooks.
-
- 
-
-3. Select the Hook you want to enable.
-4. Confirm your selection by clicking **YES, ENABLE HOOK**.
-
- 
-
-You will now see a green dot next to the name of the Hook, indicating that it's enabled.
-
-## Disable a Hook
-
-1. Navigate to [the Hooks page of the Dashboard](${manage_url}/#/hooks) and find the extensibility point for which you want an enabled Hook.
-2. Immediately under the name and description of the extensibility point, click on the dropdown box that lists all of the point's associated Hooks.
-
- 
-
-3. Select **None**.
-4. Confirm your selection by clicking **YES, DISABLE HOOK**.
-
- 
\ No newline at end of file
diff --git a/articles/hooks/dashboard/index.md b/articles/hooks/dashboard/index.md
deleted file mode 100644
index 18fed1500a..0000000000
--- a/articles/hooks/dashboard/index.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-description: How to create new Hooks using the Management Dashboard
-url: /hooks/dashboard
-beta: true
----
-
-# Work with Hooks in the Dashboard
-
-
-
-The Auth0 Management Dashboard provides a visual interface for working with Hooks. With the Dashboard, you can:
-
-* [Create/Delete New Hooks](/hooks/dashboard/create-delete)
-* [Enable/Disable Existing Hooks](/hooks/dashboard/enable-disable)
-* [Edit Existing Hooks](/hooks/dashboard/edit)
\ No newline at end of file
diff --git a/articles/hooks/delete.md b/articles/hooks/delete.md
new file mode 100644
index 0000000000..cdc18884aa
--- /dev/null
+++ b/articles/hooks/delete.md
@@ -0,0 +1,56 @@
+---
+title: Delete Hooks
+description: Learn how to delete Hooks using the Dashboard and Management API. Hooks may also be imported and exported using the Auth0 Deploy Command-Line Interface (CLI) tool.
+topics:
+ - hooks
+ - mgmt-api
+ - dashboard
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+# Delete Hooks
+
+When you no longer need Hooks, you can delete them using either the Dashboard or Management API.
+
+Hooks may also be imported and exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
+
+
+
+## Delete Hooks using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the gear icon next to the Hook you want to delete.
+2. Select **Delete**, and confirm.
+
+
+
+## Delete Hooks using the Management API
+
+1. Make a `DELETE` call to the [Delete a Hook endpoint](/api/management/v2/#!/Hooks/delete_hooks_by_id). Be sure to replace `HOOK_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your hook ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "DELETE",
+ "url": "https://${account.namespace}/api/v2/hooks/HOOK_ID",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| Value | Description |
+| - | - |
+| `HOOK_ID` | ID of the Hook you would like to delete. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `delete:hooks`. |
+
+
+
+
diff --git a/articles/hooks/enable-disable.md b/articles/hooks/enable-disable.md
new file mode 100644
index 0000000000..29db93e2a5
--- /dev/null
+++ b/articles/hooks/enable-disable.md
@@ -0,0 +1,76 @@
+---
+title: Enable/Disable Hooks
+description: Learn how to enable and disable Hooks using the Dashboard and Management API.
+topics:
+ - hooks
+ - dashboard
+ - mgmt-api
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# Enable/Disable Hooks
+
+You can enable or disable Hooks that have been configured for any given [extensibility point](/hooks/extensibility-points) using the Dashboard or Management API.
+
+<%= include('./_includes/_hook_enabled_limit') %>
+
+<%= include('./_includes/_default_hook_enable_behavior') %>
+
+
+
+## Enable/Disable Hooks using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and locate the extensibility point for which you want to enable or disable a Hook.
+
+2. Click on the dropdown box located immediately under the extensibility point's name and description.
+
+ 
+
+3. Select the Hook you want to enable, and confirm. If you want to disable all Hooks, select `None`.
+
+A green dot will appear next to the name of any enabled Hooks.
+
+
+
+## Enable/Disable Hooks using the Management API
+
+1. Make a `PATCH` call to the [Update a Hook endpoint](/api/management/v2/#!/Hooks/patch_hooks_by_id). Be sure to replace `HOOK_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your hook ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/hooks/HOOK_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"enabled\": \"true\" }"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `HOOK_ID` | ID of the hook to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `update:hooks`. |
+
+::: note
+The `enabled` property represents whether the rule is enabled (`true`) or disabled (`false`). |
+:::
+
+
+
+
diff --git a/articles/hooks/extensibility-points/client-credentials-exchange.md b/articles/hooks/extensibility-points/client-credentials-exchange.md
new file mode 100644
index 0000000000..1d447b40f7
--- /dev/null
+++ b/articles/hooks/extensibility-points/client-credentials-exchange.md
@@ -0,0 +1,263 @@
+---
+title: Client Credentials Exchange
+description: Learn how hooks can be used with the Client Credentials Exchange extensibility point, which is available for database connections and passwordless connections.
+toc: true
+topics:
+ - hooks
+ - extensibility-points
+ - client-credentials-exchange
+ - credentials-exchange
+contentType:
+ - how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# Client Credentials Exchange
+
+At the Client Credentials Exchange extensibility point, Hooks allow custom actions to be executed when an Access Token is issued through the Authentication API [`POST /oauth/token` endpoint](/api/authentication#client-credentials-flow) using the [Client Credentials Flow](/flows/concepts/client-credentials). For example, you may deny the token from being issued, add custom claims to the Access Token, or modify its scopes.
+
+Hooks at this extensibility point are blocking (synchronous), which means they execute as part of the trigger's process and will prevent the rest of the Auth0 pipeline from running until the Hook is complete.
+
+::: note
+The `triggerId` for the Client Credentials Exchange extensibility point is `credentials-exchange`. To learn how to create Hooks for this extensibility point, see [Create New Hooks](/hooks/create).
+:::
+
+To learn about other extensibility points, see [Extensibility Points](/hooks/extensibility-points).
+
+## Starter code and parameters
+
+When creating a Hook executed at the Client Credentials Exchange extensibility point, you may find the following starter code helpful. Parameters that can be passed into and used by the Hook function are listed at the top of the code sample.
+
+```js
+/**
+@param {object} client - client information
+@param {string} client.name - client name
+@param {string} client.id - client ID
+@param {string} client.tenant - Auth0 tenant name
+@param {object} client.metadata - client metadata
+@param {array|undefined} scope - either an array of strings representing the token's scope claim, or undefined
+@param {string} audience - token's audience claim
+@param {object} context - Auth0 context info
+@param {object} context.webtask - Hook (webtask) context
+@param {function} cb - function (error, accessTokenClaims)
+*/
+
+module.exports = function(client, scope, audience, context, cb) {
+ var access_token = {};
+ access_token.scope = scope; // do not remove this line
+
+ // Modify scopes or add extra claims
+ // access_token['https://example.com/claim'] = 'bar';
+ // access_token.scope.push('extra');
+
+ // Deny the token and respond with an OAuth2 error response
+ // if (denyExchange) {
+ // // To return an HTTP 400 with { "error": "invalid_scope", "error_description": "Not authorized for this scope." }
+ // return cb(new InvalidScopeError('Not authorized for this scope.'));
+ //
+ // // To return an HTTP 400 with { "error": "invalid_request", "error_description": "Not a valid request." }
+ // return cb(new InvalidRequestError('Not a valid request.'));
+ //
+ // // To return an HTTP 500 with { "error": "server_error", "error_description": "A server error occurred." }
+ // return cb(new ServerError('A server error occurred.'));
+ // }
+
+ cb(null, access_token);
+};
+```
+
+Please note:
+
+* The callback function (`cb`) at the end of the sample code signals completion and *must* be included.
+- The line `access_token.scope = scope` ensures that all granted scopes will be present in the Access Token. Removing it will reset all scopes, and the token will include only any scopes you might add with the script.
+
+### Default response
+
+When you run a Hook executed at the Client Credentials Exchange extensibility point, the default response object is:
+
+```json
+{
+ "scope": "array of strings"
+}
+```
+
+### Starter code response
+
+Once you've customized the starter code with your scopes and additional claims, you can test the Hook using the Runner embedded in the Hook Editor. The Runner simulates a call to the Hook with the same body and response that you would get with a Client Credentials Exchange.
+
+<%= include('../_includes/_test_runner_save_warning') %>
+
+When you run a Hook based on the starter code, the response object is:
+
+```json
+{
+ "audience": "https://my-tenant.auth0.com/api/v2/",
+ "client": {
+ "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "name": "client-name",
+ "tenant": "my-tenant",
+ "metadata": {
+ "plan": "full"
+ }
+ },
+ "scope": [
+ "read:connections"
+ ]
+}
+```
+
+## Sample script: Add an additional scope to the Access Token
+
+In this example, we use a Hook to add an additional [scope](/scopes) to those already existing for the Access Token.
+
+```js
+module.exports = function(client, scope, audience, context, cb) {
+ // Scopes to be added
+ var access_token = {};
+
+ // Get the scope that's currently on the Access Token
+ // and add it to the object we're working with
+ // Do not remove this line!
+ access_token.scope = scope;
+
+ // Append the `read:resource` scope
+ access_token.scope.push('read:resource');
+
+ // Callback to indicate completion and to return new
+ // array of scopes
+ cb(null, access_token);
+};
+```
+
+### Response
+
+When we run this Hook, the response object is:
+
+```json
+{
+ "scope": [
+ "read:connections",
+ "read:resource"
+ ]
+}
+```
+
+## Sample script: Add a claim to the Access Token
+
+In this example, we add a [namespaced](/tokens/guides/create-namespaced-custom-claims) custom claim and its value to the Access Token.
+
+You can add the following as claims to the issued token:
+
+* The `scope` property of the response object
+* Any properties with [namespaced](/tokens/concepts/claims-namespacing) property names
+
+The extensibility point will ignore all other response object properties.
+
+<%= include('../_includes/_access_hook_secrets') %>
+
+```js
+module.exports = function(client, scope, audience, context, cb) {
+ // Claims to be added
+ var access_token = {};
+
+ // New claim to add to the token
+ access_token['https://example.com/foo'] = 'bar';
+
+ // Callback to indicate completion and to return new claim
+ cb(null, access_token);
+ };
+```
+
+### Response
+
+When we run this Hook, the response object is:
+
+```json
+{
+ "https://example.com/foo": "bar"
+}
+```
+
+## Sample script: Raise an Error or Deny an Access Token
+
+In this example, we use custom Error objects to generate OAuth2 Error Responses. ([See OAuth2 RFC - Section 5.2](https://tools.ietf.org/html/rfc6749#section-5.2))
+
+If a plain JavaScript error is returned in the callback, such as:
+
+```js
+module.exports = function(client, scope, audience, context, cb) {
+ // Callback to indicate completion and to return new claim
+ cb(new Error("Unknown error occurred.");
+ };
+```
+
+Then when you request a `client_credentials` grant from the `/oauth/token` endpoint, Auth0 will respond with:
+
+```
+HTTP 500
+{ "error": "server_error", "error_description": "Unknown error occurred." }
+```
+
+However, if you like additional control over the OAuth2 Error Response, three custom Error objects are available to use instead. They are:
+
+### InvalidScopeError
+
+```js
+module.exports = function(client, scope, audience, context, cb) {
+ const invalidScope = ...; // determine if scope is valid
+
+ if(invalidScope) {
+ cb(new InvalidScopeError("Scope is not permitted."));
+ }
+ };
+```
+
+Then when you request a `client_credentials` grant is from the `/oauth/token` endpoint, Auth0 will respond with:
+
+```
+HTTP 400
+{ "error": "invalid_scope", "error_description": "Scope is not permitted." }
+```
+
+### InvalidRequestError
+
+```js
+module.exports = function(client, scope, audience, context, cb) {
+ const invalidRequest = ...; // determine if request is valid
+
+ if(invalidRequest) {
+ cb(new InvalidRequestError("Bad request."));
+ }
+ };
+```
+
+Then when you request a `client_credentials` grant from the `/oauth/token` endpoint, Auth0 will respond with:
+
+```
+HTTP 400
+{ "error": "invalid_request", "error_description": "Bad request." }
+```
+
+### ServerError
+
+```js
+module.exports = function(client, scope, audience, context, cb) {
+ callOtherService(function(err, response) {
+ if(err) {
+ return cb(new ServerError("Error calling remote system: " + err.message));
+ }
+ });
+ };
+```
+
+Then when you request a `client_credentials` grant from the `/oauth/token` endpoint, Auth0 will respond with:
+
+```
+HTTP 400
+{ "error": "server_error", "error_description": "Error calling remote system: ..." }
+```
+
+::: note
+Currently, the behavior of the built-in JavaScript `Error` class and `ServerError` is identical, but the `ServerError` class allows you to be explicit about the OAuth2 error that will be returned.
+:::
diff --git a/articles/hooks/extensibility-points/credentials-exchange.md b/articles/hooks/extensibility-points/credentials-exchange.md
deleted file mode 100644
index 4117d61609..0000000000
--- a/articles/hooks/extensibility-points/credentials-exchange.md
+++ /dev/null
@@ -1,162 +0,0 @@
----
-title: Using the Credentials Exchange Extensibility Point
-description: The credentials-exchange extensibility point for use with Hooks
-toc: true
-beta: true
----
-
-# Extensibility Point: Credentials Exchange
-
-The `credentials-exchange` extensibility point allows you to change the scopes and add custom claims to the [Access Tokens](/tokens/access-token) issued by the [Auth0 API's `POST /oauth/token` endpoint](/api/authentication#authorization-code) during runtime.
-
-::: note
-Please see [Calling APIs from a Service](/api-auth/grant/client-credentials) for more information on the Client Credentials Grant.
-:::
-
-## Types of Claims Available
-
-You can add the following as claims to the issued token:
-
-* The `scope` property of the response object;
-* Any properties with namespaced property names:
-
- * URLs with HTTP or HTTPS schemes
- * URLs with hostnames that *aren't* auth0.com, webtask.io, webtask.run, or the associated subdomain names
-
-The extensibility point will ignore all other response object properties.
-
-::: note
-If you need to configure client secrets and access them within your Hook, you can do so using `context.webtask.secrets.SECRET_NAME`.
-:::
-
-## How to Implement This
-
-You can implement a [Hook](/hooks#work-with-hooks) using this extensibility point with either the [Dashboard](/hooks/dashboard) or the [Command Line Interface](/hooks/cli).
-
-For detailed steps on implementing the grant, please refer to [Using Hooks with Client Credentials Grant](/api-auth/tutorials/client-credentials/customize-with-hooks).
-
-### Starter Code and Parameters
-
-After you've created a new Hook that uses the Credentials Exchange extensibility point, you can open up the Hook and edit it using the Webtask Editor embedded in the Dashboard.
-
-The parameters listed in the comment at the top of the code indicate the Auth0 objects (and the parameters within the objects) that can be passed into and used by the Hook's function. For example, the `client` object comes with the following parameters: client name, client ID, the Auth0 tenant name with which the client is associated, and client metadata.
-
-```js
-/**
-@param {object} client - information about the client
-@param {string} client.name - name of client
-@param {string} client.id - client id
-@param {string} client.tenant - Auth0 tenant name
-@param {object} client.metadata - client metadata
-@param {array|undefined} scope - array of strings representing the scope claim or undefined
-@param {string} audience - token's audience claim
-@param {object} context - additional authorization context
-@param {object} context.webtask - webtask context
-@param {function} cb - function (error, accessTokenClaims)
-*/
-module.exports = function(client, scope, audience, context, cb) {
- var access_token = {};
- access_token.scope = scope;
-
- // Modify scopes or add extra claims
- // access_token['https://example.com/claim'] = 'bar';
- // access_token.scope.push('extra');
-
- cb(null, access_token);
-};
-```
-
-The callback function `cb` at the end of the sample code is used to signal completion and must not be omitted.
-
-#### Response
-
-The default response object every time you run this Hook is as follows:
-
-```json
-{
- "scope": "array of strings"
-}
-```
-
-### Testing Your Hook
-
-::: note
-Executing the code using the Runner requires a save, which means that your original code will be overwritten.
-:::
-
-Once you've modified the sample code with the specific scopes of additional claims you'd like added to your Access Tokens, you can test your Hook using the Runner. The runner simulates a call to the Hook with the same body/payload that you would get with a Credentials Exchange. The following is the sample body that populates the Runner by default (these are the same objects/parameters detailed in the comment at the top of the sample Hook code):
-
-```json
-{
- "audience": "https://my-tenant.auth0.com/api/v2/",
- "client": {
- "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
- "name": "client-name",
- "tenant": "my-tenant",
- "metadata": {
- "plan": "full"
- }
- },
- "scope": [
- "read:connections"
- ]
-}
-```
-
-## Example: Add Scope to the Access Token
-
-This example shows you how to use the Hook to add an additional scope to the scopes already existing on the Access Token.
-
-```js
-module.exports = function(client, scope, audience, context, cb) {
- // Scopes to be added
- var access_token = {};
-
- // Get the scope that's currently on the Access Token
- // and add it to the object we're working with
- access_token.scope = scope;
-
- // Append the `read:resource` scope
- access_token.scope.push('read:resource');
-
- // Callback to indicate completion and to return new
- // array of scopes
- cb(null, access_token);
-};
-```
-
-Using the [test runner](https://webtask.io/docs/editor/runner), we see that the response is as follows:
-
-```json
-{
- "scope": [
- "read:connections",
- "read:resource"
- ]
-}
-```
-
-## Example: Add a Claim to the Access Token
-
-This example show you have to add a namespaced claim and its value to the Access Token.
-
-```js
-module.exports = function(client, scope, audience, context, cb) {
- // Claims to be added
- var access_token = {};
-
- // New claim to add to the token
- access_token['https://example.com/foo'] = 'bar';
-
- // Callback to indicate completion and to return new claim
- cb(null, access_token);
- };
-```
-
-Using the [test runner](https://webtask.io/docs/editor/runner), we see that the response is as follows:
-
-```json
-{
- "https://example.com/foo": "bar"
-}
-```
\ No newline at end of file
diff --git a/articles/hooks/extensibility-points/index.md b/articles/hooks/extensibility-points/index.md
index 85b2a78920..c39ebc9aa5 100644
--- a/articles/hooks/extensibility-points/index.md
+++ b/articles/hooks/extensibility-points/index.md
@@ -1,13 +1,27 @@
---
-description: The extensibility points for use with Hooks
-url: /hooks/extensibility-points
-beta: true
+description: Learn about extensibility points of the Auth0 platform that are available to use with Hooks.
+topics:
+ - hooks
+ - extensibility-points
+contentType:
+ - reference
+useCase: extensibility-hooks
---
# Extensibility Points
-Hooks allow you to customize the behavior of Auth0 with Node.js code. They are essentially [Webtask](https://webtask.io), but [Hooks](/hooks#work-with-hooks) are executed only against selected extensibility points, which are the serverless option that's analagous to the webhooks that come with a server. The following is a list of currently available extensibility points:
+Extensibility points are places in the Auth0 platform where [Hooks](/hooks) can be executed.
-- [Credentials Exchange](/hooks/extensibility-points/credentials-exchange): change the scopes and add custom claims to the tokens issued by the Auth0 API's `POST /oauth/token` endpoint
-- [Pre-User Registration](/hooks/extensibility-points/pre-user-registration): prevent user registration and add custom metadata to a newly-created user
-- [Post-User Registration](/hooks/extensibility-points/post-user-registration): implement custom actions that execute asynchronously from the Auth0 authentication process after a new user registers and is added to the database
\ No newline at end of file
+Whether Hooks can be used with connections varies according to extensibility point. Hooks that can be used with connections only work with [Database Connections](/connections/database) and [Passwordless Connections](/connections/passwordless).
+
+Extensibility points may also block processes from executing. Synchronous extensibility points are blocking, which means they execute the Hook as part of the trigger's process and will prevent that process from executing until the Hook is complete. Aynchronous extensibility points will not wait for the Hook to finish its execution before proceeding.
+
+The following extensibility points are available:
+
+| Extensibility Point | Trigger ID | Connection Type(s) | Blocking? | Description |
+|---------------------|-----------|-----------------|-------------|-------------------|
+| [Client Credentials Exchange](/hooks/extensibility-points/client-credentials-exchange) | `credentials-exchange` | N/A | Yes | Extend machine-to-machine token exchanges. Prevent a token exchange or change the scopes and add custom claims to access tokens issued by the Auth0 API's `POST /oauth/token` endpoint. |
+| [Pre-User Registration](/hooks/extensibility-points/pre-user-registration) | `pre-user-registration` | Database, Passwordless | Yes | Prevent user creation or registration, or add custom metadata to a newly-created user. |
+| [Post-User Registration](/hooks/extensibility-points/post-user-registration) | `post-user-registration` | Database, Passwordless | No | Implement custom actions from the Auth0 authentication process after a new user is created or registers and is added to the database. |
+| [Post-Change Password](/hooks/extensibility-points/post-change-password) | `post-change-password` | Database | No | Implement custom actions to be executed after a successful user password change. |
+| [Send Phone Message](/hooks/extensibility-points/send-phone-message) | `send-phone-message` | N/A | Yes | Implement a custom phone messaging provider to deliver MFA one-time-use codes. |
diff --git a/articles/hooks/extensibility-points/post-change-password.md b/articles/hooks/extensibility-points/post-change-password.md
new file mode 100644
index 0000000000..4a26db63aa
--- /dev/null
+++ b/articles/hooks/extensibility-points/post-change-password.md
@@ -0,0 +1,128 @@
+---
+title: Post-Change Password
+description: Learn how hooks can be used with the Post Change Password extensibility point, which is available for database connections.
+toc: true
+topics:
+ - hooks
+ - extensibility-points
+ - post-change-password
+contentType:
+ - how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# Post-Change Password
+
+At the Post-Change Password extensibility point, Hooks allow custom actions to be executed after a successful user password change, whether initiated by a user for their own password or by a tenant administrator for another user's password. For example, you may send an email to a user to notify them that their password has been changed.
+
+Hooks at this extensibility point are non-blocking (asynchronous), which means the Auth0 pipeline will continue to run without waiting for a Hook to finish its execution. Thus, the Hook's outcome does not affect the Auth0 transaction.
+
+The Post-Change Password extensibility point is available for [Database Connections](/connections/database).
+
+::: note
+The `triggerId` for the Post-Change Password extensibility point is `post-change-password`. To learn how to create Hooks for this extensibility point, see [Create New Hooks](/hooks/create).
+:::
+
+To learn about other extensibility points, see [Extensibility Points](/hooks/extensibility-points).
+
+## Starter code and parameters
+
+When creating a Hook executed at the Post-Change Password extensibility point, you may find the following starter code helpful. Parameters that can be passed into and used by the Hook function are listed at the top of the code sample.
+
+```js
+/**
+@param {object} user - affected user
+@param {string} user.id - user's ID
+@param {string} user.username - user's username
+@param {string} user.email - user's email
+@param {string} user.last_password_reset - date/time the user's password was last changed
+@param {object} context - Auth0 context info, such as connection
+@param {object} context.connection - connection info
+@param {object} context.connection.id - connection ID
+@param {object} context.connection.name - connection name
+@param {object} context.connection.tenant - connection tenant
+@param {object} context.webtask - Hook (webtask) context
+@param {function} cb - function (error)
+**/
+
+module.exports = function (user, context, cb) {
+ // Perform any asynchronous actions, e.g. send notification to Slack.
+ cb();
+};
+```
+
+Please note:
+
+* The callback function (`cb`) at the end of the sample code signals completion and *must* be included.
+
+### Default response
+
+Hooks executed at the Post-Change Password extensibility point ignore any response object. If an error is returned, a tenant log entry is created, but this does not affect the Auth0 transaction.
+
+### Starter code response
+
+Once you've customized the starter code, you can test the Hook using the Runner embedded in the Hook Editor. The Runner simulates a call to the Hook with the appropriate body and response.
+
+<%= include('../_includes/_test_runner_save_warning') %>
+
+When you run a Hook based on the starter code, the response object is:
+
+```json
+{
+ "user": {
+ "id": "abc123",
+ "username": "user1",
+ "email": "user1@foo.com",
+ "last_password_reset": "2019-02-27T14:14:29.206Z"
+ },
+ "context": {
+ "connection": {
+ "id": "con_xxxxxxxxxxxxxxxx",
+ "name": "Username-Password-Authentication",
+ "tenant": "my-tenant"
+ }
+ }
+}
+```
+
+## Sample script: Send a notification email upon password change
+
+In this example, we use a Hook to have SendGrid send a notification email to the user upon password change. The example requires a valid SendGrid API key to be stored in [Hook Secrets](/hooks/secrets) as `SENDGRID_API_KEY`.
+
+```js
+module.exports = function (user, context, cb) {
+
+ const request = require('request');
+ const sendgridApiKey = context.webtask.secrets.SENDGRID_API_KEY;
+
+ // https://sendgrid.api-docs.io/v3.0/mail-send
+ request.post({
+ url: 'https://api.sendgrid.com/v3/mail/send',
+ headers: {
+ 'Authorization': 'Bearer ' + sendgridApiKey
+ },
+ json: {
+ personalizations: [{
+ to: [{
+ email: user.email
+ }]
+ }],
+ from: {
+ email: 'admin@example.com'
+ },
+ subject: 'Your password was changed',
+ content: [{
+ type: 'text/plain',
+ value: 'The password for your ' + context.connection.name + ' account ' + user.email + ' was recently changed.'
+ }]
+ }
+ }, function (err, resp, body) {
+ if (err || resp.statusCode !== 202) {
+ return cb(err || new Error(body.errors[0].message));
+ }
+
+ cb();
+ });
+};
+```
diff --git a/articles/hooks/extensibility-points/post-user-registration.md b/articles/hooks/extensibility-points/post-user-registration.md
index 1e785ee835..694ee52253 100644
--- a/articles/hooks/extensibility-points/post-user-registration.md
+++ b/articles/hooks/extensibility-points/post-user-registration.md
@@ -1,69 +1,78 @@
---
-title: Using the Post-User Registration Extensibility Point
-description: The post-user-registration extensibility point for use with Hooks
-beta: true
+title: Post-User Registration
+description: Learn how hooks can be used with the Post-User Registration extensibility point, which is available for database connections and passwordless connections.
toc: true
+topics:
+ - hooks
+ - extensibility-points
+ - post-user-registration
+contentType:
+ - how-to
+useCase: extensibility-hooks
+v2: true
---
-# Extensibility Point: Post-User Registration
+# Post-User Registration
-For [Database Connections](/connections/database), the `post-user-registration` extensibility point allows you to implement custom actions that execute after a new user registers and is added to the database. [Hooks](/hooks#work-with-hooks) associated with the `post-user-registration` extensibility point execute asynchronously from the actions that are a part of the Auth0 authentication process.
+At the Post-User Registration extensibility point, Hooks allow custom actions to be executed after a new user registers an account and is added to the database. For example, you may send a message to Slack or create a record in your customer relationship management (CRM) system.
-This allows you to implement scenarios including (but not limited to):
+Hooks at this extensibility point are non-blocking (asynchronous), which means the Auth0 pipeline will continue to run without waiting for a Hook to finish its execution. Thus, the Hook's outcome does not affect the Auth0 transaction.
-* Sending notifications to Slack or via e-mail about the user's new account;
-* Creating a new user record in a CRM system.
+The Post-User Registration extensibility point is available for [Database Connections](/connections/database) and [Passwordless Connections](/connections/passwordless).
-## How to Implement This
-
-You can implement a [Hook](/hooks#work-with-hooks) using this extensibility point with either the [Dashboard](/hooks/dashboard) or the [Command Line Interface](/hooks/cli).
+::: note
+The `triggerId` for the Post-User Registration extensibility point is `post-user-registration`. To learn how to create Hooks for this extensibility point, see [Create New Hooks](/hooks/create).
+:::
-### Starter Code and Parameters
+To learn about other extensibility points, see [Extensibility Points](/hooks/extensibility-points).
-After you've created a new Hook that uses the Post-User Registration extensibility point, you can open up the Hook and edit it using the Webtask Editor embedded in the Dashboard.
+## Starter code and parameters
-The parameters listed in the comment at the top of the code indicate the Auth0 objects (and the parameters within the objects) that can be passed into and used by the Hook's function. For example, the `client` object comes with the following parameters: application name, client ID, the Auth0 tenant name with which the application is associated, and application metadata.
+When creating a Hook executed at the Post-User Registration extensibility point, you may find the following starter code helpful. Parameters that can be passed into and used by the Hook function are listed at the top of the code sample.
```js
/**
-@param {object} user - The user being created
-@param {string} user.id - user id
+@param {object} user - user being created
+@param {string} user.id - user's ID (user GUID without "auth0|" database prefix)
@param {string} user.tenant - Auth0 tenant name
-@param {string} user.username - user name
-@param {string} user.email - email
-@param {boolean} user.emailVerified - is e-mail verified?
-@param {string} user.phoneNumber - phone number
-@param {boolean} user.phoneNumberVerified - is phone number verified?
-@param {object} user.user_metadata - user metadata
-@param {object} user.app_metadata - application metadata
-@param {object} context - Auth0 connection and other context info
+@param {string} user.username - user's username
+@param {string} user.email - user's email
+@param {boolean} user.emailVerified - indicates whether email is verified
+@param {string} user.phoneNumber - user's phone number
+@param {boolean} user.phoneNumberVerified - indicates whether phone number is verified
+@param {object} user.user_metadata - user's user metadata
+@param {object} user.app_metadata - user's application metadata
+@param {object} context - Auth0 context info, such as connection
@param {string} context.requestLanguage - language of the application agent
-@param {object} context.connection - information about the Auth0 connection
-@param {object} context.connection.id - connection id
+@param {object} context.connection - connection info
+@param {object} context.connection.id - connection ID
@param {object} context.connection.name - connection name
@param {object} context.connection.tenant - connection tenant
-@param {object} context.webtask - webtask context
+@param {object} context.webtask - Hook (webtask) context
@param {function} cb - function (error, response)
*/
+
module.exports = function (user, context, cb) {
// Perform any asynchronous actions, such as send notification to Slack.
cb();
};
```
-The callback function `cb` at the end of the sample code is used to signal completion and must not be omitted (even though the extensibility point ignores response objects).
+Please note:
-#### Response
+* The callback function (`cb`) at the end of the sample code signals completion and *must* be included.
-The Post-User Registration extensibility point ignores any response object.
+### Default response
-### Testing Your Hook
+Hooks executed at the Post-User Registration extensibility point ignore any response object.
-::: note
-Executing the code using the Runner requires a save, which means that your original code will be overwritten.
-:::
+### Starter code response
+
+Once you've customized the starter code, you can test the Hook using the Runner embedded in the Hook Editor. The Runner simulates a call to the Hook with the appropriate body and response.
+
+<%= include('../_includes/_test_runner_save_warning') %>
-Once you've modified the sample code with the specific scopes of additional claims you'd like added to your Access Tokens, you can test your Hook using the Runner. The runner simulates a call to the Hook with the appropriate user information body/payload. The following is the sample body that populates the Runner by default (these are the same objects/parameters detailed in the comment at the top of the sample Hook code):
+When you run a Hook based on the starter code, the response object is:
```json
{
@@ -92,7 +101,9 @@ Once you've modified the sample code with the specific scopes of additional clai
}
```
-## Example: Integrate with Slack
+## Sample script: Integrate with Slack
+
+In this example, we use a Hook to have Slack post a new user's username and email address to a specified channel upon user registration.
```js
module.exports = function (user, context, cb) {
@@ -102,7 +113,7 @@ module.exports = function (user, context, cb) {
// Post the new user's name and email address to the selected channel
var slack = require('slack-notify')(SLACK_HOOK);
- var message = 'New User: ' + (user.name || user.email) + ' (' + user.email + ')';
+ var message = 'New User: ' + (user.username || user.email) + ' (' + user.email + ')';
var channel = '#some_channel';
slack.success({
@@ -113,4 +124,4 @@ module.exports = function (user, context, cb) {
// Return immediately; the request to the Slack API will continue on the sandbox
cb();
};
-```
\ No newline at end of file
+```
diff --git a/articles/hooks/extensibility-points/pre-user-registration.md b/articles/hooks/extensibility-points/pre-user-registration.md
index 572f317734..6291fd715e 100644
--- a/articles/hooks/extensibility-points/pre-user-registration.md
+++ b/articles/hooks/extensibility-points/pre-user-registration.md
@@ -1,49 +1,61 @@
---
-title: Using the Pre-User Registration Extensibility Point
-description: The pre-user-registration extensibility point for use with Hooks
+title: Pre-User Registration
+description: Learn how hooks can be used with the Pre-User Registration extensibility point, which is available for database connections and passwordless connections.
toc: true
-beta: true
+topics:
+ - hooks
+ - extensibility-points
+ - pre-user-registration
+contentType:
+ - how-to
+useCase: extensibility-hooks
+v2: true
---
-# Extensibility Point: Pre-User Registration
+# Pre-User Registration
-For [Database Connections](/connections/database), the `pre-user-registration` extensibility point allows you to add custom `app_metadata` or `user_metadata` to a newly-created user.
+At the Pre-User Registration extensibility point, Hooks allow custom actions to be executed when a new user is created. For example, you may add custom `app_metadata` or `user_metadata` to the newly-created user, or even prevent the creation of the user in the database.
-This allows you to implement scenarios such as setting conditional [metadata](/metadata) on users that do not exist yet.
+Hooks at this extensibility point are blocking (synchronous), which means they execute as part of the trigger's process and will prevent the rest of the Auth0 pipeline from running until the Hook is complete.
-## How to Implement This
+The Pre-User Registration extensibility point is available for [Database Connections](/connections/database) and [Passwordless Connections](/connections/passwordless).
-You can implement a [Hook](/hooks#work-with-hooks) using this extensibility point with either the [Dashboard](/hooks/dashboard) or the [Command Line Interface](/hooks/cli).
+::: note
+The `triggerId` for the Pre-User Registration extensibility point is `pre-user-registration`. To learn how to create Hooks for this extensibility point, see [Create New Hooks](/hooks/create).
+:::
-## Starter Code and Parameters
+To learn about other extensibility points, see [Extensibility Points](/hooks/extensibility-points).
-After you've created a new Hook that uses the Pre-User Registration extensibility point, you can open up the Hook and edit it using the Webtask Editor embedded in the Dashboard.
+## Starter code and parameters
-The parameters listed in the comment at the top of the code indicate the Auth0 objects (and the parameters within the objects) that can be passed into and used by the Hook's function. For example, the `client` object comes with the following parameters: application name, client ID, the Auth0 tenant name with which the application is associated, and application metadata.
+When creating a Hook executed at the Pre-User Registration extensibility point, you may find the following starter code helpful. Parameters that can be passed into and used by the Hook function are listed at the top of the code sample.
```js
/**
-@param {object} user - The user being created
+@param {object} user - user being created
@param {string} user.tenant - Auth0 tenant name
-@param {string} user.username - user name
+@param {string} user.username - user's username
@param {string} user.password - user's password
-@param {string} user.email - email
-@param {boolean} user.emailVerified - is e-mail verified?
-@param {string} user.phoneNumber - phone number
-@param {boolean} user.phoneNumberVerified - is phone number verified?
-@param {object} context - Auth0 connection and other context info
-@param {string} context.requestLanguage - language of the application agent
-@param {object} context.connection - information about the Auth0 connection
-@param {object} context.connection.id - connection id
+@param {string} user.email - user's email
+@param {boolean} user.emailVerified - indicates whether email is verified
+@param {string} user.phoneNumber - user's phone number
+@param {boolean} user.phoneNumberVerified - indicates whether phone number is verified
+@param {object} context - Auth0 context info, such as connection
+@param {string} context.renderLanguage - language of the signup flow
+@param {string} context.request.ip - ip address
+@param {string} context.request.language - language of the application agent
+@param {object} context.connection - connection info
+@param {object} context.connection.id - connection ID
@param {object} context.connection.name - connection name
@param {object} context.connection.tenant - connection tenant
-@param {object} context.webtask - webtask context
-@param {function} cb - function (error, response)
+@param {object} context.webtask - Hook (webtask) context
+@param {function} cb - Function (error, response)
*/
+
module.exports = function (user, context, cb) {
var response = {};
- // Add user or app metadata to the newly created user
+ // Add user or app metadata to the newly-created user
// response.user = {
// user_metadata: { foo: 'bar' },
// app_metadata: { vip: true, score: 7 }
@@ -55,11 +67,13 @@ module.exports = function (user, context, cb) {
};
```
-The callback function `cb` at the end of the sample code is used to signal completion and must not be omitted.
+Please note:
-### Response
+* The callback function (`cb`) at the end of the sample code signals completion and *must* be included.
+
+### Default response
-The default response object every time the Hook runs is similar to the following:
+When you run a Hook executed at the Pre-User Registration extensibility point, the default response object is:
```json
{
@@ -87,13 +101,17 @@ If you specify `app_metadata` and `user_metadata` in the response object, Auth0
Metadata property names must not start with the `$` character or contain the `.` character.
:::
-## Testing Your Hook
-
::: note
-Executing the code using the Runner requires a save, which means that your original code will be overwritten.
+Hooks executed at the Pre-User Registration extensibility point do not pass error messages to any Auth0 APIs.
:::
-Once you've modified the sample code with the specific scopes of additional claims you'd like added to your Access Tokens, you can test your Hook using the Runner. The runner simulates a call to the Hook with the appropriate user information body/payload. The following is the sample body that populates the Runner by default (these are the same objects/parameters detailed in the comment at the top of the sample Hook code):
+### Starter code response
+
+Once you've customized the starter code, you can test the Hook using the Runner embedded in the Hook Editor. The Runner simulates a call to the Hook with the appropriate body and response.
+
+<%= include('../_includes/_test_runner_save_warning') %>
+
+When you run a Hook based on the starter code, the response object is:
```json
{
@@ -113,7 +131,10 @@ Once you've modified the sample code with the specific scopes of additional clai
}
},
"context": {
- "requestLanguage": "en-us",
+ "request": {
+ "language": "en-us",
+ "ip": "123.123.123.123"
+ },
"connection": {
"id": "con_xxxxxxxxxxxxxxxx",
"name": "Username-Password-Authentication",
@@ -123,7 +144,9 @@ Once you've modified the sample code with the specific scopes of additional clai
}
```
-## Example: Add Metadata to New Users
+## Sample script: Add metadata to new users
+
+In this example, we use a Hook to add metadata to new users upon creation.
```js
module.exports = function (user, context, cb) {
@@ -138,7 +161,9 @@ module.exports = function (user, context, cb) {
};
```
-Using the [test runner](https://webtask.io/docs/editor/runner), we see that the response, reflecting the updated metadata, is as follows:
+### Response
+
+When we run this Hook, the response object is:
```json
{
@@ -154,6 +179,27 @@ Using the [test runner](https://webtask.io/docs/editor/runner), we see that the
}
```
-::: note
-The Pre-Registration Hook does not currently pass error messages to any Auth0 APIs.
-:::
\ No newline at end of file
+## Sample script: Customize the error message and language for user messages
+
+In this example, we use a Hook to prevent a user from registering, then return a custom error message in our tenant logs and show a custom, translated error message to the user when they are denied. To return the user message and use the translation functionality, your tenant must be configured to use the [Universal Login - New Experience](/universal-login/new).
+
+```js
+module.exports = function (user, context, cb) {
+ const isUserDenied = ...; // determine if a user should be allowed to register
+
+ if (isUserDenied) {
+ const LOCALIZED_MESSAGES = {
+ en: 'You are not allowed to register.',
+ es: 'No tienes permitido registrarte.'
+ };
+
+ const localizedMessage = LOCALIZED_MESSAGES[context.renderLanguage] || LOCALIZED_MESSAGES['en'];
+ return cb(new PreUserRegistrationError('Denied user registration in Pre-User Registration Hook', localizedMessage));
+ }
+};
+```
+
+Please note:
+* The custom `PreUserRegistrationError` class allows you to control the message seen by the user who is attempting to register.
+* The first parameter passed to `PreUserRegistrationError` controls the error message that appears in your tenant logs.
+* The second parameter controls the error message seen by the user who is attempting to register. In this example, the `context.renderLanguage` parameter generates a user-facing message in the appropriate language for the user. You can use these parameters only if your tenant is configured to use the [Universal Login - New Experience](/universal-login/new).
diff --git a/articles/hooks/extensibility-points/send-phone-message.md b/articles/hooks/extensibility-points/send-phone-message.md
new file mode 100644
index 0000000000..89ec90acf3
--- /dev/null
+++ b/articles/hooks/extensibility-points/send-phone-message.md
@@ -0,0 +1,138 @@
+---
+title: Send Phone Message
+description: Learn how to provide your own code to send phone messages for MFA
+toc: true
+topics:
+ - hooks
+ - extensibility-points
+ - send-phone-message
+ - custom-messaging-gateway
+ - sms
+ - voice
+contentType:
+ - how-to
+useCase: extensibility-hooks
+v2: true
+---
+# Send Phone Message
+
+If you decide to use SMS or Voice as a factor for Multi-factor Authentication (MFA), you can configure how you want Auth0 to send the messages in the [MFA Phone configuration dialog](/mfa/guides/configure-phone#administrative-setup).
+
+If you select the 'Custom' delivery method, you must create a **Send Phone Message Hook** that will let you write your own code to send the message. This allows you to use whatever messaging provider you want.
+
+Hooks at this extensibility point are blocking (synchronous), which means they execute as part of the trigger's process and will prevent the rest of the Auth0 pipeline from running until the Hook is complete.
+
+::: note
+The `triggerId` for the Send Phone Message extensibility point is `send-phone-message`. To learn how to create Hooks for this extensibility point, see [Create New Hooks](/hooks/create).
+:::
+
+To learn about other extensibility points, see [Extensibility Points](/hooks/extensibility-points).
+
+## Starter code and parameters
+
+When creating a Hook executed at the Send Phone Message extensibility point, you may find the following starter code helpful. Parameters that can be passed into and used by the Hook function are listed at the top of the code sample.
+
+```js
+/**
+@param {string} recipient - phone number
+@param {string} text - message body
+@param {object} context - additional authorization context
+@param {string} context.message_type - 'sms' or 'voice'
+@param {string} context.action - 'enrollment' or 'second-factor-authentication'
+@param {string} context.language - language used by login flow
+@param {string} context.code - one-time password
+@param {string} context.ip - ip address
+@param {string} context.user_agent - user agent making the authentication request
+@param {object} context.client - object with details about the Auth0 application
+@param {string} context.client.client_id - Auth0 application ID
+@param {string} context.client.name - Auth0 application name
+@param {object} context.client.client_metadata - metadata from client
+@param {object} context.user - object representing the user
+@param {string} context.user.user_id - Auth0 user's ID
+@param {string} context.user.name - user's name
+@param {string} context.user.email - user 'semail
+@param {object} context.user.app_metadata - metadata specific to user and application
+@param {object} context.user.user_metadata - metadata specific to user
+@param {function} cb - function (error, response)
+*/
+module.exports = function(recipient, text, context, cb) {
+ // TODO: Add your code here
+ cb(null, {});
+};
+```
+
+::: note
+The callback function (`cb`) at the end of the sample code signals completion and **must** be included.
+:::
+
+## Example parameters
+
+This is an example of the parameters:
+
+```js
+{
+ "recipient": "1-808-555-5555",
+ "text": "Here is your one time password: 999111",
+ "context": {
+ "message_type": "sms",
+ "action": "enrollment",
+ "language": "en",
+ "code": "123456",
+ "ip": "127.0.0.1",
+ "user_agent": "Mozilla/5.0",
+ "client": {
+ "client_id": "1235",
+ "name": "Test Application",
+ "client_metadata": { }
+ },
+ "user": {
+ "user_id": "auth0|test12345",
+ "name": "Billie Magnusson",
+ "email": "billie@email.com",
+ "app_metadata": { },
+ "user_metadata": { }
+ }
+ }
+}
+```
+
+## Starter code response
+
+Once you have customized the Hook code, you can test it using the Runner embedded in the Editor. The Runner simulates a call to the Hook with the appropriate body and response.
+
+<%= include('../_includes/_test_runner_save_warning') %>
+
+When you run a Hook based on the starter code, the response object is:
+
+```
+{
+ "MessageID": "998a9ad1-c9b9-4b85-97b1-ac0305aa5532"
+}
+```
+
+## Localization
+
+The `context.language` parameter will always have one of the [languages configured in the Tenant Settings](/universal-login/i18n). Depending on how you trigger the MFA flow, we will calculate which language to use in the following different ways:
+
+- If you use the [MFA API](/mfa/concepts/mfa-api), we will use the Accept-Language header from the request and map it to a tenant language. If the language is not available, we will set the parameter to the tenant default language.
+
+- If you use the New Universal Login Experience, we will use a combination of the Accept-Language header and the `ui_locales` parameter, as described in [Universal Login Internationalization](/universal-login/i18n#language-selection).
+
+- If you use the Classic Universal Login Experience, we will set the language to 'N/A'. This is a limitation that will be fixed in upcoming releases.
+
+## Examples
+
+Learn how to integrate different messaging providers with the examples below:
+
+* [Amazon SNS](/mfa/send-phone-message-hook-amazon-sns)
+* [Twilio](/mfa/send-phone-message-hook-twilio)
+* [Infobip](/mfa/send-phone-message-hook-infobip)
+* [TeleSign](/mfa/send-phone-message-hook-telesign)
+* [Vonage](/mfa/send-phone-message-hook-vonage)
+* [Esendex](/mfa/send-phone-message-hook-esendex)
+* [Mitto](/mfa/send-phone-message-hook-mitto)
+
+## Keep Reading
+
+- [Configure SMS or Voice Notifications for MFA](/mfa/guides/configure-phone)
+- [Extensibility Points](/hooks/extensibility-points)
diff --git a/articles/hooks/index.md b/articles/hooks/index.md
index 2c14134ba2..ee230d7323 100644
--- a/articles/hooks/index.md
+++ b/articles/hooks/index.md
@@ -1,51 +1,46 @@
---
-url: /hooks
-classes: topic-page
title: Hooks
-description: Working with Hooks
-beta: true
+description: Learn about Auth0 Hooks for Database Connections and Passwordless Connections.
+topics:
+ - hooks
+ - extensibility-points
+contentType:
+ - index
+ - concept
+useCase: extensibility-hooks
---
+# Hooks
-
-
-
Hooks
-
- Hooks allow you to extend the Auth0 platform with custom code.
-
-
-
-## What are Hooks?
-
-When using [Database Connections](/connections/database), Hooks allow you to customize the behavior of Auth0 using Node.js code that is executed against extensibility points (which are comparable to webhooks that come with a server). Hooks allow you modularity when configuring your Auth0 implementation, and extend the functionality of base Auth0 features.
-
-## Work with Hooks
-
-
- How to work with Hooks using the Auth0 Command-Line Interface
-
-
-
-
-## Use the Webtask Editor
-
-You can edit Hooks directly using the Webtask Editor. Please see the [Webtask documentation](https://webtask.io/docs/editor) for detailed information.
+<%= include('../_includes/_ip_whitelist') %>
+
+Hooks are secure, self-contained functions that allow you to customize the behavior of Auth0 when executed for selected [extensibility points](/hooks/extensibility-points) of the Auth0 platform. Auth0 invokes Hooks during runtime to execute your custom Node.js code.
+
+Whether Hooks can be used with connections varies according to extensibility point. Hooks that can be used with connections only work with [Database Connections](/connections/database) and [Passwordless Connections](/connections/passwordless).
+
+## Manage Hooks
+
+You can create, update, delete, enable/disable, and view Hooks from the Dashboard or Management API. To learn more, see:
+
+- [Create Hooks](/hooks/create)
+- [Update Hooks](/hooks/update)
+- [Delete Hooks](/hooks/delete)
+- [Enable/Disable Hooks](/hooks/enable-disable)
+- [View Hooks](/hooks/view)
+
+Hooks may also be imported and exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
+
+<%= include('./_includes/_handle_rate_limits') %>
+
+## Manage Hook Secrets
+
+Hooks feature integrated secret management to securely store secrets while making them conveniently available in code. To learn more, see [Hook Secrets](/hooks/secrets).
+
+## Test Hooks
+
+The Hooks editor in the Dashboard has an integrated Runner, which allows you to test your code without leaving the editor.
+
+<%= include('./_includes/_test_runner_save_warning') %>
+
+## View Logs
+
+You can view real-time logging information for specific configured Hooks using the Dashboard. To learn more, see [View Logs for Hooks](/hooks/view-logs).
diff --git a/articles/hooks/overview.md b/articles/hooks/overview.md
deleted file mode 100644
index bc135c0bc6..0000000000
--- a/articles/hooks/overview.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-description: >-
- Hooks are JavaScript functions executed as part of the user
- authentication flow. They allow you to customize and extend Auth0's
- capabilities, and you can chain them together for modular coding.
-beta: true
----
-
-# Hooks: Overview
-
-Hooks, which will eventually replace [Rules](/rules), allow you to extend the Auth0 platform with custom code.
-
-Hooks are Webtasks associated with specific extensibility points of the Auth0 platform. When using [Database Connections](/connections/database), Auth0 invokes the Hooks at runtime to execute your custom logic.
-
-You can manage your Hooks using:
-
-* [The Auth0 Management Dashboard](/hooks/dashboard)
-* [The Auth0 Command-Line Interface (CLI)](/hooks/cli).
-
-## Supported Extensibility Points
-
-You can create Hooks for the following [extensibility points](/hooks/extensibility-points):
-
-- [Credentials Exchange](/hooks/extensibility-points/credentials-exchange)
-- [Pre-User Registration](/hooks/extensibility-points/pre-user-registration)
-- [Post-User Registration](/hooks/extensibility-points/post-user-registration)
\ No newline at end of file
diff --git a/articles/hooks/secrets/create.md b/articles/hooks/secrets/create.md
new file mode 100644
index 0000000000..071f5318d8
--- /dev/null
+++ b/articles/hooks/secrets/create.md
@@ -0,0 +1,71 @@
+---
+title: Create Hook Secrets
+description: Learn how to create Hook Secrets using the Dashboard and Management API. Hook Secrets may also be imported and exported using the Auth0 Deploy Command-Line Interface (CLI) tool.
+topics:
+ - hooks
+ - secrets
+ - dashboard
+ - mgmt-api
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# Create Hook Secrets
+
+You can create multiple Hook Secrets for any [Hook](/hooks) using the Dashboard or Management API.
+
+Hook Secrets may also be imported and exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
+
+<%= include('../_includes/_hook_secrets_limit') %>
+
+
+
+## Create Hook Secrets using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the pencil icon next to the Hook you want to edit.
+2. In the Hook editor, click the wrench icon, and click **Secrets**.
+3. Click **Add Secret**.
+4. Enter a descriptive name and value for your secret, and click **Save**.
+
+
+
+
+## Create Hook Secrets using the Management API
+
+1. Make a `POST` call to the [Add Hook Secrets endpoint](/api/management/v2/#!/Hooks/post_secrets). Be sure to replace `MGMT_API_ACCESS_TOKEN`, `HOOK_ID`, `HOOK_SECRET_KEY`, and `HOOK_SECRET_VALUE` placeholder values with your Management API Access Token, Hook ID, and Hook key-value pair(s), respectively.
+
+```har
+{
+ "method": "POST",
+ "url": "https://${account.namespace}/api/v2/hooks/HOOK_ID/secrets",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ [ \"HOOK_SECRET_KEY\", \"HOOK_SECRET_VALUE\" ], [ \"HOOK_SECRET_KEY\", \"HOOK_SECRET_VALUE\" ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:hooks`. |
+| `HOOK_ID` | ID of the hook for which you would like to add secrets. |
+| `HOOK_SECRET_KEY` | Name of the secret that you would like to add to the specified hook. This endpoint accepts an object of key-value pairs. |
+| `HOOK_SECRET_VALUE` | Value of the secret that you would like to add to the specified hook. This endpoint accepts an object of key-value pairs. |
+
+
+
+
diff --git a/articles/hooks/secrets/delete.md b/articles/hooks/secrets/delete.md
new file mode 100644
index 0000000000..128a697d81
--- /dev/null
+++ b/articles/hooks/secrets/delete.md
@@ -0,0 +1,64 @@
+---
+title: Delete Hook Secrets
+description: Learn how to delete Hook Secrets using the Dashboard and Management API. Hook Secrets may also be imported and exported using the Auth0 Deploy Command-Line Interface (CLI) tool.
+topics:
+ - hooks
+ - secrets
+ - mgmt-api
+ - dashboard
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+# Delete Hook Secrets
+
+When you no longer need Hook Secrets for a given [Hook](/hooks), you can delete them using either the Dashboard or Management API.
+
+Hook Secrets may also be imported and exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
+
+
+
+## Delete Hook Secrets using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the pencil icon next to the Hook you want to edit.
+2. In the Hook editor, click the wrench icon, and click **Secrets**.
+3. Locate the Hook Secret you want to delete, click the trash can icon, and confirm.
+
+
+
+
+## Delete Hook Secrets using the Management API
+
+1. Make a `DELETE` call to the [Delete Hook Secrets endpoint](/api/management/v2/#!/Hooks/delete_secrets). Be sure to replace `HOOK_ID`, `HOOK_SECRET_NAME`, and `MGMT_API_ACCESS_TOKEN` placeholder values with your hook ID, your hook secret name(s), and Management API Access Token, respectively.
+
+```har
+{
+ "method": "DELETE",
+ "url": "https://${account.namespace}/api/v2/hooks/HOOK_ID/secrets",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ [ \"HOOK_SECRET_NAME\", \"HOOK_SECRET_NAME\" ] }"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `HOOK_ID` | ID of the Hook for which you want to delete secrets. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `delete:hooks`. |
+| `HOOK_SECRET_NAME` | Name(s) of the secret(s) you would like to delete from the specified Hook. This endpoint accepts an array of secret names to delete. |
+
+
+
+
diff --git a/articles/hooks/secrets/index.md b/articles/hooks/secrets/index.md
new file mode 100644
index 0000000000..aab126f146
--- /dev/null
+++ b/articles/hooks/secrets/index.md
@@ -0,0 +1,26 @@
+---
+title: Hook Secrets
+description: Learn about integrated secret management used with Auth0 Hooks.
+topics:
+ - hooks
+ - secrets
+contentType:
+ - concept
+useCase: extensibility-hooks
+---
+# Hook Secrets
+
+[Hooks](/hooks) feature integrated secret management to securely store secrets while making them conveniently available in code.
+
+<%= include('../_includes/_access_hook_secrets') %>
+
+## Manage Hook Secrets
+
+You can create, update, delete, and view Hook Secrets from the Dashboard or Management API. To learn more, see:
+
+- [Create Hook Secrets](/hooks/secrets/create)
+- [Update Hook Secrets](/hooks/secrets/update)
+- [Delete Hook Secrets](/hooks/secrets/delete)
+- [View Hook Secrets](/hooks/secrets/view)
+
+ Hook Secrets may also be imported or exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
diff --git a/articles/hooks/secrets/update.md b/articles/hooks/secrets/update.md
new file mode 100644
index 0000000000..4ee4c59e79
--- /dev/null
+++ b/articles/hooks/secrets/update.md
@@ -0,0 +1,73 @@
+---
+title: Update Hook Secrets
+description: Learn how to update Hook Secrets using the Dashboard or Management API. Hook Secrets may also be imported and exported using the Auth0 Deploy Command-Line Interface (CLI) tool.
+topics:
+ - hooks
+ - secrets
+ - dashboard
+ - mgmt-api
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# Update Hook Secrets
+
+You can update Hook Secrets added to any given [Hook](/hooks) using the Dashboard or Management API.
+
+Hook Secrets may also be imported and exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
+
+
+
+## Update Hook Secrets using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the pencil icon next to the Hook you want to edit.
+2. In the Hook editor, click the wrench icon, and click **Secrets**.
+3. Click the pencil and paper icon next to the value of the secret you want to edit.
+4. Make your changes to the name and/or value of the selected secret, and click **Save**.
+
+
+
+
+## Update Hook Secrets using the Management API
+
+1. Make a `PATCH` call to the [Update Hook Secrets endpoint](/api/management/v2/#!/Hooks/patch_secrets). Be sure to replace `HOOK_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your hook ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/hooks/HOOK_ID/secrets",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{ [ \"HOOK_SECRET_KEY\", \"HOOK_SECRET_VALUE\" ], [ \"HOOK_SECRET_KEY\", \"HOOK_SECRET_VALUE\" ] }"
+ }
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `create:hooks`. |
+| `HOOK_ID` | ID of the hook for which you would like to update secrets. |
+| `HOOK_SECRET_KEY` | Name of the secret that you would like to update for the specified hook. This endpoint accepts an object of key-value pairs. |
+| `HOOK_SECRET_VALUE` | Value of the secret that you would like to update for the specified hook. This endpoint accepts an object of key-value pairs. |
+
+::: warning
+When retrieving secrets configured for a specified hook, values will contain the placeholder text: `_VALUE_NOT_SHOWN`. Be careful not to return this placeholder text during an update, or the secret's actual value will be overwritten.
+:::
+
+
+
+
diff --git a/articles/hooks/secrets/view.md b/articles/hooks/secrets/view.md
new file mode 100644
index 0000000000..0760ba1468
--- /dev/null
+++ b/articles/hooks/secrets/view.md
@@ -0,0 +1,63 @@
+---
+title: View Hook Secrets
+description: Learn how to view Hook Secrets using the Dashboard and Management API.
+topics:
+ - hooks
+ - secrets
+ - mgmt-api
+ - dashboard
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+# View Hook Secrets
+
+To see configured secrets for a [Hook](/hooks), you can view them using the Dashboard or retrieve a list of them using the Management API.
+
+
+
+## View Hook Secrets using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the pencil icon next to the Hook for which you want to view secrets.
+
+2. In the Hook editor, click the wrench icon, and click **Secrets**.
+
+All configured secrets for the selected Hook will be listed.
+
+
+
+
+## Get Hook Secrets using the Management API
+
+1. Make a `GET` call to the [Get Hook Secrets endpoint](/api/management/v2/#!/Hooks/get_secrets). Be sure to replace `HOOK_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your Hook's ID and the Management API Access Token, respectively.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/hooks/HOOK_ID/secrets",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `HOOK_ID` | ID of the Hook for which you want to retrieve secrets. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `read:hooks`. |
+
+::: warning
+Secrets are write-only. When retrieving secrets configured for a specified hook, values will contain the placeholder text: `_VALUE_NOT_SHOWN`.
+:::
+
+
+
+
diff --git a/articles/hooks/update.md b/articles/hooks/update.md
new file mode 100644
index 0000000000..06a288e13a
--- /dev/null
+++ b/articles/hooks/update.md
@@ -0,0 +1,92 @@
+---
+title: Update Hooks
+description: Learn how to update Hooks using the Dashboard or Management API. Hooks may also be imported and exported using the Auth0 Deploy Command-Line Interface (CLI) tool.
+topics:
+ - hooks
+ - dashboard
+ - mgmt-api
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# Update Hooks
+
+You can update Hooks configured for any given [extensibility point](/hooks/extensibility-points) using the Dashboard or Management API.
+
+Hooks may also be imported and exported using the [Deploy Command-Line Interface (CLI) Extension](/extensions/deploy-cli).
+
+::: note
+If you added a [Hook Secret](/hooks/secrets) and want to update it, see [Update Hook Secrets](/hooks/secrets/update).
+:::
+
+
+
+## Rename Hooks using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the gear icon next to the Hook you want to rename.
+2. Select **Rename**.
+3. Enter the current name and new name of the hook, then click **Rename**.
+
+
+
+## Update Hook scripts using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the pencil icon next to the Hook you want to update.
+
+ 
+
+2. Update the Hook using the Hook Editor, and click the disk icon to save.
+
+ 
+
+
+
+## Update Hooks using the Management API
+
+1. Make a `PATCH` call to the [Update a Hook endpoint](/api/management/v2/#!/Hooks/patch_hooks_by_id). Be sure to replace `HOOK_ID` and `MGMT_API_ACCESS_TOKEN` placeholder values with your hook ID and Management API Access Token, respectively.
+
+```har
+{
+ "method": "PATCH",
+ "url": "https://${account.namespace}/api/v2/hooks/HOOK_ID",
+ "headers": [
+ { "name": "Content-Type", "value": "application/json" },
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" },
+ { "name": "Cache-Control", "value": "no-cache" }
+ ],
+ "postData": {
+ "mimeType": "application/json",
+ "text" : "{ \"name\": \"HOOK_NAME\", \"script\": \"HOOK_SCRIPT\", \"enabled\": \"true\" }"
+ }
+}
+```
+
+| Value | Description |
+| - | - |
+| `HOOK_ID` | ID of the hook to be updated. |
+| `MGMT_API_ACCESS_TOKEN` | [Access Tokens for the Management API](/api/management/v2/tokens) with the scope `update:hooks`. |
+| `HOOK_NAME` | Name of the hook you would like to create. |
+| `HOOK_SCRIPT` | Script that contains the code for the hook. Should match what you would enter if you were creating a new hook using the Dashboard. |
+
+::: note
+The `enabled` property represents whether the rule is enabled (`true`) or disabled (`false`). |
+:::
+
+
+
+
+
+<%= include('./_includes/_handle_rate_limits') %>
+
+::: note
+Optionally, you can add secrets (such as Twilio Keys or database connection strings) to Hooks. To learn how to update secrets, see [Update Hook Secrets](/hooks/secrets/update).
+:::
diff --git a/articles/hooks/view-logs.md b/articles/hooks/view-logs.md
new file mode 100644
index 0000000000..af51d1f9b5
--- /dev/null
+++ b/articles/hooks/view-logs.md
@@ -0,0 +1,21 @@
+---
+title: View Logs for Hooks
+description: Learn how to view logs for Hooks using the Auth0 Dashboard.
+topics:
+ - hooks
+ - logs
+ - dashboard
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+
+# View Logs for Hooks
+
+You can view real-time logging information for specific configured Hooks using the Dashboard.
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/), and click the pencil icon next to the Hook you want to update.
+
+ 
+
+2. In the Hooks Editor, click the logs icon.
diff --git a/articles/hooks/view.md b/articles/hooks/view.md
new file mode 100644
index 0000000000..498e623194
--- /dev/null
+++ b/articles/hooks/view.md
@@ -0,0 +1,55 @@
+---
+title: View Hooks
+description: Learn how to view Hooks using the Dashboard and Management API. Hooks may also be imported and exported using the Auth0 Deploy Command-Line Interface (CLI) tool.
+topics:
+ - hooks
+ - mgmt-api
+ - dashboard
+contentType: how-to
+useCase: extensibility-hooks
+v2: true
+---
+# View Hooks
+
+To see configured Hooks, you can view them using the Dashboard or retrieve a list of them using the Management API.
+
+
+
+## View Hooks using the Dashboard
+
+1. Navigate to the [Hooks](${manage_url}/#/hooks) page in the [Auth0 Dashboard](${manage_url}/).
+
+All configured Hooks will be listed by the extensibility point at which they are executed. A green dot next to a Hook indicates that it is enabled.
+
+
+
+
+## Get Hooks using the Management API
+
+1. Make a `GET` call to the [Get Hooks endpoint](/api/management/v2/#!/Hooks/get_hooks). Be sure to replace `MGMT_API_ACCESS_TOKEN` placeholder value with your Management API Access Token.
+
+```har
+{
+ "method": "GET",
+ "url": "https://${account.namespace}/api/v2/hooks",
+ "headers": [
+ { "name": "Authorization", "value": "Bearer MGMT_API_ACCESS_TOKEN" }
+ ]
+}
+```
+
+| **Value** | **Description** |
+| - | - |
+| `MGMT_API_ACCESS_TOKEN` | [Access Token for the Management API](/api/management/v2/tokens) with the scope `read:hooks`. |
+
+
+
+
diff --git a/articles/hosted-pages/custom-error-pages.md b/articles/hosted-pages/custom-error-pages.md
deleted file mode 100644
index 7ce87d71ad..0000000000
--- a/articles/hosted-pages/custom-error-pages.md
+++ /dev/null
@@ -1,81 +0,0 @@
----
-title: Custom Error Pages
-description: How to setup a custom error page for authorization error events.
-toc: true
-crews: crew-2
----
-# Custom Error Pages
-
-In the event of an authorization error, you may choose to display to your users either [the default Auth0 error page](/hosted-pages/error-pages) or a customized error page.
-
-This article will show you how to use a customized error page. For details on the default Auth0 error page see [Error Pages](/hosted-pages/error-pages).
-
-## How to customize the error page
-
-If you choose to display a custom error page, you have two options:
-
-- [Redirect the user to a custom error page](#redirect-users-to-a-custom-error-page)
-- [Configure Auth0 to render a custom error page on your behalf](#render-a-custom-error-page). This feature is only available via the Management API.
-
-### Redirect users to a custom error page
-
-You can configure Auth0 to redirect users to a custom error page, using the Dashboard or the Management API.
-
-If you use the Dashboard, follow these steps:
-
-1. Log in to the [Dashboard](${manage_url}).
-1. Click on your tenant name in the top right corner to bring up the associated dropdown box.
-1. Select **Settings** to open the [Tenant Settings](${manage_url}/#/tenant/) page.
-1. Scroll down to the Error Pages section.
-1. Select the option **Redirect users to your own error page**.
-1. Provide the URL of the error page you would like your users to see.
-
-
-
-If you use the API instead, use the `PATCH /api/v2/tenants/settings` endpoint. Update the `url` field of your JSON body to point to the location of the error page.
-
-```har
-{
- "method": "PATCH",
- "url": "https://${account.namespace}/api/v2/tenants/settings",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [
- { "name": "Authorization", "value": "Bearer YOUR_TOKEN"},
- { "name": "Content-Type", "value": "application/json" }
- ],
- "queryString" : [],
- "postData": {
- "mimeType": "application/json",
- "text": "{\"error_page\": {\"html\": \"\", \"show_log_link\":false, \"url\": \"http://www.example.com\"}}"
- },
- "headersSize" : -1,
- "bodySize" : -1,
- "comment" : ""
-}
-```
-
-### Render a custom error page
-
-To provide the appropriate HTML, pass in a string containing the appropriate Liquid syntax to the `html` element:
-
-```har
-{
- "method": "PATCH",
- "url": "https://login.auth0.com/api/v2/tenants/settings",
- "httpVersion": "HTTP/1.1",
- "cookies": [],
- "headers": [
- { "name": "Authorization", "value": "Bearer YOUR_TOKEN"},
- { "name": "Content-Type", "value": "application/json" }
- ],
- "queryString" : [],
- "postData": {
- "mimeType": "application/json",
- "text": "{\"error_page\": {\"html\": \"
Hello {{name}}. This error was generated {{'now' | date: '%Y %h'}}.<\\h1>\", \"show_log_link\": false, \"url\": \"\"}}"
- },
- "headersSize" : -1,
- "bodySize" : -1,
- "comment" : ""
-}
-```
diff --git a/articles/hosted-pages/error-pages.md b/articles/hosted-pages/error-pages.md
deleted file mode 100644
index df02ed9daa..0000000000
--- a/articles/hosted-pages/error-pages.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-description: Guide on how to use the hosted error pages for authorization error events
-crews: crew-2
----
-
-# Error Pages
-
-## Generic Error Page
-
-Throughout the authentication process, your users may encounter errors. Auth0 provides you the option of using [custom error pages](/hosted-pages/custom-error-pages), but you may also choose to use the generic error page that Auth0 provides.
-
-
-
-By going into the [Tenant Settings](${manage_url}/#/tenant/) page of the Management Dashboard, you may customize your Auth0 error page with the following fields:
-
-* **Friendly Name**: the name of your company;
-* **Logo URL**: the URL to your company logo;
-* **Support Email**: the email address of your company's support team;
-* **Support URL**: the URL to your company's support page.
-
-In addition to these fields, the error page returns the follow information to assist you in troubleshooting the error:
-
-* **Client ID**: the identifier for the client;
-* **Connection**: the Connection used at the time of error;
-* **Language**: the language set to be used at the time of error;
-* **Error**: the code corresponding to the error that occurred;
-* **Error Description**: a description of the error that occurred;
-* **Show Log URL**: the link to the error logs, if available;
-* **Title**: the friendly name of the tenant;
-* **Tenant**: the tenant information (the friendly name, logo URL, support email, and support URL fields that you may customize).
-
-## Custom Error Pages
-
-In the event of an authorization error, you may choose to display to your users either the default Auth0 error page or a customized error page.
-
-The [custom error pages](/hosted-pages/custom-error-pages) page details how you can configure your own custom error page for use with Auth0.
diff --git a/articles/hosted-pages/guardian.md b/articles/hosted-pages/guardian.md
deleted file mode 100644
index 67e6d096f8..0000000000
--- a/articles/hosted-pages/guardian.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-description: Guide on how to use the hosted Guardian MFA page
----
-# Guardian Multifactor Login Page
-
-In the [Auth0 Dashboard](${manage_url}/#/guardian_mfa_page), you can enable 2nd factor authentication, using Guardian Multifactor. You can customize the page that Auth0 displays to your users, allowing you to require MFA on logins which meet certain criteria, or just across the board. For more information on Guardian, refer to [Guardian MFA](/multifactor-authentication/guardian).
-
-
-
-## Guardian Login Page HTML Editor
-
-To enable the Guardian Login page, go to [Dashboard > Hosted Pages > Guardian Multifactor](${manage_url}/#/guardian_mfa_page) and enable the __Customize Guardian Page__ switch.
-
-Once you do that, you'll be able to use the text editor built into the Auth0 Dashboard to change your HTML, style your page using CSS, and alter the JavaScript used to retrieve custom variables. Once you've made your changes, and make sure to click __Save__.
-
-If you'd like to revert to an earlier design, you have two options:
-
-* Reverting to the last saved template by clicking **Reset to Last**;
-* Reverting to the default template provided by Auth0 by clicking **Reset to Default**.
diff --git a/articles/hosted-pages/index.md b/articles/hosted-pages/index.md
deleted file mode 100644
index 95513db8e1..0000000000
--- a/articles/hosted-pages/index.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-description: Overview of hosted pages with Auth0, and how to use them
----
-
-# Auth0 Hosted Pages
-
-Auth0 offers you the ability to display customized pages containing Auth0-related functionality and to which Auth0 redirects your users during the authorization process. You can create the following types of hosted pages:
-
-* [Login](/hosted-pages/login)
-* [Password Reset](/hosted-pages/password-reset)
-* [Guardian Multifactor](/hosted-pages/guardian)
-* [Error pages](/hosted-pages/error-pages)
-
-While Auth0 hosts your custom pages, you can still [manage your pages using the version control system of your choice](/hosted-pages/version-control).
-
-## Why Use Hosted Pages
-
-Hosted pages are easy to implement and secure. For example, using Auth0 hosted pages instead of hosting them externally provides seamless CSRF protection. This helps prevent third party impersonation or the hijacking of sessions.
-
-## How to Enable and Customize Hosted Pages
-
-To enable a particular type of hosted page, navigate to the [Hosted Pages section of the Auth0 Dashboard](${manage_url}/#/login_page) (note that Error Page settings are located under [Tenant Settings](${manage_url}/#/tenant)). Click on the slider to enable the page.
-
-## Customize Your Hosted Page
-
-In the Auth0 Dashboard, you'll see an HTML editor, as well as a **Preview** tab, for each of the hosted page types. You can either use the editor to create your HTML or paste in the HTML you've created elsewhere.
-
-For detailed instructions on how to customize each type of hosted page, please see the following docs:
-
-* [Login Page](/hosted-pages/login)
-* [Password Reset Page](/hosted-pages/password-reset)
-* [Guardian Multifactor Authentication Page](/hosted-pages/guardian)
-* [Error Pages](/error-pages)
diff --git a/articles/hosted-pages/login/auth0js.md b/articles/hosted-pages/login/auth0js.md
deleted file mode 100644
index 0dd64f2da4..0000000000
--- a/articles/hosted-pages/login/auth0js.md
+++ /dev/null
@@ -1,181 +0,0 @@
----
-description: How to Use the Auth0.js with the Hosted Login Page
----
-# Using Auth0.js in the Hosted Login Page
-
-Within the login page, you can use the the [Auth0.js SDK](/libraries/auth0js), instead of [Lock](/libraries/lock), to perform authentication using a custom UI.
-
-## Auth0.js Template for the Login Page
-
-You can start out with a basic template that will provide you with a working, ready-to-use example of a custom UI using Auth0.js v8 in your universal login page.
-
-In the [dashboard](${manage_url}), go to **Hosted Pages**, and then to the **Login** page section.
-
-At the top of the code editor for the page contents, you'll see a dropdown, titled **Default Templates**. Here you can choose from `Lock`, `Lock Passwordless`, or `Custom UI`.
-
-Choose `Custom UI` to get started.
-
-
-
-The template showcases using Auth0.js to allow users to sign up, log in with a database connection, or login with a social provider (Google, in this example).
-
-Additionally, you can take a look at the following example scenario using Auth0.js as well.
-
-### Passwordless example
-
-With [passwordless authentication](/connections/passwordless), the user is prompted to enter an email or an SMS number, at which they will receive a one-time code to enter, or a "magic link" to click, which will authenticate them. In this example, the user will enter an email, and receive a one-time code.
-
-For this example, replace the code in the login page editor with the following template:
-
-```html
-
-
-
-
-
- Sign In with Auth0
-
-
-
-
-
-
-
-
-
-
Welcome
-
PLEASE LOG IN
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-This should allow you to prompt your users to enter their email address, receive a code, and enter it to verify. Once the transaction is complete and they're redirected to your application, you'll want to [parse the URL hash](/libraries/auth0js#extract-the-authresult-and-get-user-info) to acquire their token and finish your authentication process.
-
-## Next Steps
-
-Are you looking for more information about the SDK used here, or about Passwordless authentication? Or are you ready to get started implementing universal login?
-
-::: next-steps
-* [Read more About the Auth0.js SDK](/libraries/auth0js)
-* [Get Started with Universal Login](${manage_url}/#/login_page)
-:::
diff --git a/articles/hosted-pages/login/index.md b/articles/hosted-pages/login/index.md
index 8da2c2a94e..91c88f8d46 100644
--- a/articles/hosted-pages/login/index.md
+++ b/articles/hosted-pages/login/index.md
@@ -8,15 +8,17 @@ crews: crew-2
## About Universal Login
-Auth0's universal login is the most secure way to easily authenticate users for your applications. The login page appearance and behavior is easily customizable right from the [Dashboard](${manage_url}). By default, the login page uses Auth0's [Lock Widget](/libraries/lock) to authenticate your users, but the code of the login page can be customized to replace Lock with the Lock Passwordless widget, or an entirely custom UI can be built in its place, using the [Auth0.js SDK](/libraries/auth0js) for authentication.
+Auth0's universal login is the most secure way to easily authenticate users for your applications. The login page appearance and behavior is easily customizable right from the [Dashboard](${manage_url}). By default, the login page uses Auth0's [Lock Widget](/libraries/lock) to authenticate your users, but the code of the login page can be customized to replace Lock with the Lock Passwordless widget, or an entirely custom UI can be built in its place, using the [Auth0.js SDK](/libraries/auth0js) for authentication.
If you cannot use universal login, you can embed the Lock widget or a custom login form in your application using [cross-origin authentication](/cross-origin-authentication), but be sure to read about its limitations before choosing to do so.

+To find the default page name for the login page, see [How to Use Version Control to Manage Your Universal Login Pages](/universal-login/version-control).
+
### How Does Universal Login Work
-Auth0 shows the login page whenever something (or someone) triggers an authentication request, such as calling the `/authorize` endpoint (OIDC/OAuth) or sending a SAML login request.
+Auth0 shows the login page whenever something (or someone) triggers an authentication request, such as calling the `/authorize` endpoint (OIDC/OAuth) or sending a SAML login request.
Users will see the login page, typically with either the Lock widget or with your custom UI. Once they login, they will be redirected back to your application.
@@ -24,16 +26,16 @@ Users will see the login page, typically with either the Lock widget or with you
If the incoming authentication request includes a `connection` parameter that uses an external identity provider (such as a social provider), the login page will not display. Instead, Auth0 will direct the user to the [identity provider's](/identityproviders) login page.
:::
-#### Single Sign-On (SSO)
+#### Single Sign-on (SSO)
-If you want to use single sign on, you should use universal login rather than an embedded login solution. When a user logs in via the login page, a cookie will be created and stored. On future calls to the `authorize` endpoint, the cookie will be checked, and if SSO is achieved, the user will not ever be redirected to the login page. They will see the page only when they need to actually login.
+If you want to use Single Sign-on (SSO), you should use universal login rather than an embedded login solution. When a user logs in via the login page, a cookie will be created and stored. On future calls to the `authorize` endpoint, the cookie will be checked, and if SSO is achieved, the user will not ever be redirected to the login page. They will see the page only when they need to actually login.
This behavior occurs without the need for any modification to the login page itself. This is a simple two step process:
-1. Enable SSO for the application in the [Dashboard](${manage_url}) (Go to the Application's Settings, then scroll down to the **Use Auth0 instead of the IdP to do Single Sign On** setting and toggle it on.
+1. Enable SSO for the application in the [Dashboard](${manage_url}) (Go to the Application's Settings, then scroll down to the **Use Auth0 instead of the IdP to do Single Sign-on** setting (legacy tenants only) and toggle it on.
1. Use the [authorize endpoint](/api/authentication#authorization-code-grant) with `?prompt=none` for [silent SSO](/api-auth/tutorials/silent-authentication).
-::: note
+::: note
For more details about how SSO works, see the [SSO documentation](/sso).
:::
@@ -57,7 +59,7 @@ Currently, universal login is the **only** way to use [Passwordless](/connection
### 1. Enable Customization on the Login Page
-In the [Dashboard](${manage_url}), you can enable a custom login page by navigating to [Hosted Pages](${manage_url}/#/login_page) and enabling the **Customize Login Page** toggle.
+In the [Dashboard](${manage_url}), you can enable a custom login page by navigating to [Universal Login](${manage_url}/#/login_settings) and enabling the **Customize Login Page** toggle.

@@ -67,7 +69,7 @@ In order to get started customizing the login page, you'll first want to choose
- [Lock](/hosted-pages/login/lock) - Lock is a pre-built, customizable login widget that will allow your users to quickly and easily login to your application.
- [Lock (Passwordless Mode)](/hosted-pages/login/lock-passwordless) - Lock in Passwordless Mode uses the same Lock interface, but rather than offering identity providers as login options, will simply ask the user to enter an email or SMS number to begin a passwordless authentication transaction.
-- [Auth0.js](/hosted-pages/login/auth0js) - Auth0.js is the SDK used for interacting with the Auth0 [authentication API](/api/authentication). Primarily, you would use the SDK if you need to build your own custom login UI, or implement more complex functionality than simply allowing your users to login.
+- [Auth0.js](/hosted-pages/login/auth0js) - Auth0.js is the SDK used for interacting with the Auth0 [authentication API](/api/authentication). Primarily, you would use the SDK if you need to build your own custom login UI, or implement more complex functionality than simply allowing your users to login.
### 3. Customization
@@ -77,7 +79,7 @@ All changes to the page's appearance and/or behavior will apply to **all** users
#### Parameters for the Authorize Endpoint
-If you initiate universal login via the `authorize` endpoint, whether by an SDK like auth0.js or by calling the endpoint directly, you may also pass some customization parameters to the login page. However, parameters passed to the `authorize` endpoint must be [OIDC specification](http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) compliant parameters.
+If you initiate universal login via the `authorize` endpoint, whether by an SDK like auth0.js or by calling the endpoint directly, you may also pass some customization parameters to the login page. However, parameters passed to the `authorize` endpoint must be [OpenID Connect (OIDC) specification](http://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) compliant parameters.
The `config` object contains the set of configuration values that adjusts the behavior of the login page at runtime. Set the `config` object up in the login page editor so that you can access the config parameters to use in your page:
@@ -85,7 +87,7 @@ The `config` object contains the set of configuration values that adjusts the be
var config = JSON.parse(decodeURIComponent(escape(window.atob('@@config@@'))));
```
-The below examples assume that you are using [Auth0.js](/libraries/auth0js) within your application to call the `authorize` endpoint and show the login page.
+The below examples assume that you are using [Auth0.js](/libraries/auth0js) within your application to call the `authorize` endpoint and show the login page.
##### Callback URL
@@ -103,19 +105,19 @@ webAuth.authorize({
## Configure Multiple Pages by Using Separate Tenants
-In some cases, you might have multiple apps and want to configure separate login pages for each. Since the hosted pages are configured in the [Dashboard](${manage_url}) at the tenant level (every app you have set up on a single tenant would use the same login page), you would have to create a new tenant for each application that requires a different hosted page.
+In some cases, you might have multiple apps and want to configure separate login pages for each. Since the Universal Login pages are configured in the [Dashboard](${manage_url}) at the tenant level (every app you have set up on a single tenant would use the same login page), you would have to create a new tenant for each application that requires a different login page.
In most cases, it would be preferable to use a single login page, which unifies your brand and the authentication experience for your users across the various areas in which they might encounter it. Additionally, using the same pages, and the same tenant, will allow you to share the resources that would otherwise need to be separated across multiple tenants.
-Creating a separate tenant is only really a viable option for an organization that needs two or more separate sets of custom pages, such as for branding reasons. If an example corporation has multiple branded subsidiaries or products, and separate APIs for all of them, it might make sense for them to create several separate Auth0 tenants, each with their own hosted pages set up for that brand or product's specific needs.
+Creating a separate tenant is only really a viable option for an organization that needs two or more separate sets of custom pages, such as for branding reasons. If an example corporation has multiple branded subsidiaries or products, and separate APIs for all of them, it might make sense for them to create several separate Auth0 tenants, each with their own Universal Login pages set up for that brand or product's specific needs.
-Bear in mind that separating tenants with the goal of having separate hosted pages will also mean that those separate tenants will have two distinct sets of applications, users, settings, and so on as these things are not shared between tenants.
+Bear in mind that separating tenants with the goal of having separate Universal Login pages will also mean that those separate tenants will have two distinct sets of applications, users, settings, and so on as these things are not shared between tenants.
### Creating New Tenants
If your use case requires separate sets of custom pages, let's see how you would go about creating them.
-If you have five different applications, with three of them (`app1`, `app2`, `app3`) using the same set of hosted pages and the other two (`app4`, `app5`) using different ones, you would do the following:
+If you have five different applications, with three of them (`app1`, `app2`, `app3`) using the same set of Universal Login pages and the other two (`app4`, `app5`) using different ones, you would do the following:
- If you already have an account, you have a tenant configured. Configure three applications under this tenant, one to represent each app (`app1`, `app2`, `app3`), and one login page which these applications will all share.
- Create a second tenant, configure a new application for `app4`, and configure the login page for this application.
diff --git a/articles/hosted-pages/login/lock-passwordless.md b/articles/hosted-pages/login/lock-passwordless.md
deleted file mode 100644
index d964ab0147..0000000000
--- a/articles/hosted-pages/login/lock-passwordless.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-description: How to use Lock Passwordless with Universal Login
----
-# Universal Login with Lock Passwordless
-
-Using Lock Passwordless in a universal login page is the easiest and most secure implementation of [passwordless authentication](/connections/passwordless) that can be achieved. Additionally, universal login is the **only** way to perform passwordless authentication with native applications at this time.
-
-## Lock Passwordless Template
-
-You can start out with a basic template that will provide you with a working, ready-to-use example of Lock with Passwordless Mode in the login page.
-
-In the [dashboard](${manage_url}), go to **Hosted Pages**, and then to the **Login** page section.
-
-At the top of the code editor for the page contents, you'll see a dropdown, titled **Default Templates**. Here you can choose from `Lock`, `Lock Passwordless`, or `Custom UI`.
-
-Choose `Lock Passwordless` to get started.
-
-
-
-## Next Steps
-
-Are you looking for more information about Lock? Or are you ready to get started with your own login page?
-
-::: next-steps
-* [Read more about Lock](/libraries/lock)
-* [Get started on your own login page](${manage_url}/#/login_page)
-:::
diff --git a/articles/hosted-pages/login/lock.md b/articles/hosted-pages/login/lock.md
deleted file mode 100644
index c5ef0b0a41..0000000000
--- a/articles/hosted-pages/login/lock.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-description: How to use Lock with Universal Login
----
-# How to Use Lock with Universal Login
-
-[Lock](/libraries/lock) is a signup and authentication widget that provides quick and easy authentication for your application's users without requiring you to design the UI or interact manually with an Auth0 API.
-
-## Customize Lock in the Login Page
-
-The default login page for your tenant is a template that will use Lock to provide your users with an attractive interface and smooth authentication process, as discussed above. You can look over that template and use it as a starting point if you choose to customize it in any way.
-
-If you want to change any of Lock's [configurable options](/libraries/lock/configuration), you can do so using the [Hosted Pages](${manage_url}/#/login_page) editor interface. These options can alter the behavior of Lock itself, or the look and feel of the widget using the theming options. See the [configuration documentation](/libraries/lock/v11/configuration) for details on how to customize Lock.
-
-When you're done making changes to the code, click **Save** to persist the changes.
-
-
-
-## Next Steps
-
-::: next-steps
-* [Read more about Lock](/libraries/lock)
-* [Get started on your own login page](${manage_url}/#/login_page)
-:::
diff --git a/articles/hosted-pages/password-reset.md b/articles/hosted-pages/password-reset.md
deleted file mode 100644
index 8e28f7ea9f..0000000000
--- a/articles/hosted-pages/password-reset.md
+++ /dev/null
@@ -1,101 +0,0 @@
----
-description: Guide on how to use the hosted password reset page
-crews: crew-2
----
-
-# Password Reset Page
-
-The Password Reset Page allows users to change their passwords in the event that they're unable to log in. Using this page, you can maintain consistency in the appearance of your pages (login, password reset, and so on), and your users can easily change their passwords as needed.
-
-## Enable the Custom Password Reset Page
-
-Using the [Auth0 Dashboard](${manage_url}/#/password_reset), you can enable your Hosted Password Reset Page by flipping the toggle switch.
-
-
-
-## Edit the Custom Password Reset Page
-
-Once you've enabled the Password Reset Page for your tenant, you'll be able to use the text editor built into the Auth0 Dashboard to change your HTML, style your page using CSS, and alter the JavaScript used to retrieve custom variables. After you've made your changes, and make sure to click _Save_.
-
-### Custom Variables
-
-You can use JavaScript to retrieve the following custom variables:
-
-| Variable | Description |
-| - | - |
-| `email` | The email address of the user requesting the password change |
-| `ticket` | The ticket representing the given password reset request |
-| `csrf_token` | Token used to prevent CSRF activity |
-| `tenant.name` | The name associated with your Auth0 tenant |
-| `tenant.friendly_name` | The name displayed for your Auth0 tenant |
-| `tenant.picture_url` | The URL leading to the logo representing you in Auth0 |
-| `tenant.support_email` | The support email address for your company displayed to your Auth0 users |
-| `tenant.support_url` | The support URL for your company displayed to your Auth0 users |
-| `lang` | The user's language |
-| `password_policy` | The active connection's security policy You can see what this is using `${manage_url}/#/connections/database/con_YOUR-CONNECTION-ID/security`. Be sure to provide your connection ID in the URL.) |
-
-::: note
-You can set/check the values for your `tenant` variables in the **Settings** area in [Tenant Settings](${manage_url}/#/tenant)
-:::
-
-Within the Password Reset Page Editor, you'll see the following JavaScript embedded:
-
-```js
-
-```
-
-Notice that the sample template uses the `tenant.picture_url` variable to return the value entered in the **Logo URL** field of the **Settings** area in [Tenant Settings](${manage_url}/#/tenant). Auth0 will retrieve the logo at that URL and display it on the password reset widget. If Auth0 cannot resolve the URL, it'll display a default image (note that the sample snippet below has all unrelated content removed, including mandatory fields):
-
-```js
-
-```
-
-## Revert Your Changes
-
-If you'd like to revert to an earlier design, you have two options:
-
-* Reverting to the last saved template by clicking **Reset to Last**;
-* Reverting to the default template provided by Auth0 by clicking **Reset to Default**.
diff --git a/articles/hosted-pages/version-control.md b/articles/hosted-pages/version-control.md
deleted file mode 100644
index ac3f4e2bd7..0000000000
--- a/articles/hosted-pages/version-control.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-description: How to back up your hosted pages using the Auth0 version control extensions
----
-# How to Use Version Control to Manage Your Hosted Pages
-
-You can use version control software to manage the source code of your hosted pages.
-To do so, you can use the Auth0-provided extension that works with the version control system you're using:
-
-* [GitLab Extension](/extensions/gitlab-deploy#deploy-hosted-pages)
-* [GitHub Extension](/extensions/github-deploy#deploy-hosted-pages)
-* [BitBucket Extension](/extensions/bitbucket-deploy#deploy-hosted-pages)
-* [Visual Studio Team Services Extension](/extensions/visual-studio-team-services-deploy#deploy-hosted-pages)
-
-While the specific documentation pages contain detailed information for the extensions, the general deploying process requires just the following steps:
-
-1. Create a folder in your version control repository with the appropriate name (`pages`).
-2. Create an HTML page (`login.html`, `password_reset.html`, `guardian_multifactor.html`, or `error_page.html`) within your folder.
-3. Create a JSON file with the same name as your HTML page for each hosted page that you wish to source control. To enable the page, the JSON file needs to contain the following:
-
-```json
-{
- "enabled": true
-}
-```
-
-
-### File Naming Example
-
-
-```text
-your-repo/pages/error_page.html
-your-repo/pages/error_page.json
-```
diff --git a/articles/i18n/i18n-guide-android.md b/articles/i18n/i18n-guide-android.md
index dba9f51f23..c415958ffe 100644
--- a/articles/i18n/i18n-guide-android.md
+++ b/articles/i18n/i18n-guide-android.md
@@ -1,6 +1,11 @@
---
title: Android guide to i18n
description: Links to the Android guide on how to localize resource files.
+topics:
+ - i18n
+ - android
+contentType: how-to
+useCase: localize
---
# Android guide to i18n
diff --git a/articles/i18n/i18n-guide-ios.md b/articles/i18n/i18n-guide-ios.md
index e50ec405b3..d691be0649 100644
--- a/articles/i18n/i18n-guide-ios.md
+++ b/articles/i18n/i18n-guide-ios.md
@@ -1,5 +1,10 @@
---
description: This page is themguide to internationalizing an iOS application.
+topics:
+ - i18n
+ - ios
+contentType: how-to
+useCase: localize
---
# iOS guide to i18n
diff --git a/articles/i18n/index.md b/articles/i18n/index.md
index 4b0190b4d0..924045f31e 100644
--- a/articles/i18n/index.md
+++ b/articles/i18n/index.md
@@ -1,12 +1,17 @@
---
url: /i18n
description: Links to documentation on internationalizing an application.
+topics:
+ - i18n
+contentType: index
+useCase: localize
---
# Internationalization and Multilingual settings
Below you can find useful links in our documentation to handle different languages within Auth0.
- [Customizing Your Emails](/email/templates)
+- [Universal Login Internationalization](/universal-login/i18n)
- [Lock: Internationalization](/libraries/lock/i18n)
- [Password Options Translation](/i18n/password-options)
- [iOS guide to i18n](/i18n/i18n-guide-ios)
diff --git a/articles/i18n/password-options.md b/articles/i18n/password-options.md
index a31e0d9872..f1bbff1601 100644
--- a/articles/i18n/password-options.md
+++ b/articles/i18n/password-options.md
@@ -1,5 +1,11 @@
---
description: How to customize the translation of Lock password features.
+topics:
+ - i18n
+ - lock
+ - password
+contentType: how-to
+useCase: localize
---
# Password Options Translation
@@ -50,7 +56,7 @@ dict: {
passwordConfirmationPlaceholder: "confirm your new password",
passwordConfirmationMatchError: "Please ensure the password and the confirmation are the same.",
successMessage: "Your password has been reset successfully.",
- configurationError: "An error ocurred. There appears to be a misconfiguration in the form.",
+ configurationError: "An error occurred. There appears to be a misconfiguration in the form.",
networkError: "The server cannot be reached, there is a problem with the network.",
timeoutError: "The server cannot be reached, please try again.",
serverError: "There was an error processing the password reset.",
diff --git a/articles/identity-labs/01-web-sign-in/exercise-01.md b/articles/identity-labs/01-web-sign-in/exercise-01.md
new file mode 100644
index 0000000000..1b27b80792
--- /dev/null
+++ b/articles/identity-labs/01-web-sign-in/exercise-01.md
@@ -0,0 +1,203 @@
+---
+section: exercises
+description: Auth0 Digital Identity Lab 1, Exercise 1: Adding Web Sign-In
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 1, Exercise 1: Adding Web Sign-In
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/01-web-sign-in) and read through the instructions before getting started.
+:::
+
+In this exercise, you will learn how to add sign-in to an app using:
+
+- Node.js + Express
+- An Express middleware to handle checking authentication and redirecting to login
+- Auth0 as an Authorization Server
+
+
+
+A simple Node.js Express application has been created to get you started. This is a web application with two pages. The first page, served under the root path `/`, shows “Hello World” and a link (“Expenses”) to the second page. The second page, served at `/expenses`, shows a table with expenses. At this point, these expenses are hard-coded; you will learn how to consume them from an API secured with Auth0 in the next lab.
+
+1. Open your Terminal app, clone the [identity exercise repo](https://github.com/auth0/identity-102-exercises/), then go to the `/lab-01/begin` folder:
+
+```bash
+❯ git clone https://github.com/auth0/identity-102-exercises.git
+Cloning into 'identity-102-exercises'...
+
+❯ cd identity-102-exercises/lab-01/begin
+```
+
+2. Open a code editor like VS Code or Atom in the same directory (File > Open) and review the `server.js` code. This is a generic Node.js web application that uses `ejs` for views and `morgan` to log HTTP requests.
+
+3. The `.env-sample` file will be used for the environment variables you need for this lab. It’s populated with a `PORT` (the port number where the app will run) and an `APP_SESSION_SECRET` (value used to encrypt the cookie data). You will set the other values later on in the lab. For now, create a copy of this file in the same folder and name it `.env`. Run the following commands in your terminal (or copy, paste, and rename the sample file in your editor):
+
+```bash
+# Make sure we're in the right directory
+❯ pwd
+/Users/username/identity-102-exercises/lab-01/begin
+
+# Copy the .env-sample file to a new .env file that the app will use
+❯ cp .env-sample .env
+```
+
+4. In your terminal, use `npm` to install all the dependencies and start the application:
+
+```bash
+❯ npm install
+# Ignore any warnings
+
+added XX packages in X.XXs
+❯ npm start
+
+listening on http://localhost:3000
+```
+
+::: note
+If you see a message like "Error: listen EADDRINUSE :::3000" in your terminal after starting the application, this means that port 3000 is in use somewhere. Change the `PORT` value in your `.env` file to "4000" and try again.
+:::
+
+5. Open a Web browser and go to [localhost:3000](http://localhost:3000) (or `http://localhost:PORT` where PORT is the value of the environment variable, in case you changed its value). You should see a page with a “Hello World” message. Click the Expenses link to view the expenses page.
+
+
+
+6. Now, we're ready to start adding authentication! Switch to your terminal window and press `[CTRL]` + `[c]` to stop the server, then use `npm` to install the package you'll use to secure the app. The `express-openid-connect` package is a simple Express middleware that provides OpenID Connect and JWT implementation.
+
+```bash
+# Continuing from previous terminal session ...
+listening on http://localhost:3000
+^C # Command to stop the server
+❯ npm install express-openid-connect@1.0.2 --save
+# Ignore any warnings
+
++ express-openid-connect@1.0.2
+added XX packages in X.XXs
+```
+
+7. Next, update your application code to require `express-openid-client` in the `server.js` file:
+
+```js
+// lab-01/begin/server.js
+
+require('dotenv').config();
+// ... other required packages
+
+// Add the line below 👇
+const { auth } = require('express-openid-connect');
+
+// ...
+```
+
+8. Now add the authentication middleware that will be used for all application routes:
+
+```js
+// lab-01/begin/server.js
+// ...
+
+const app = express();
+app.set('view engine', 'ejs');
+app.use(morgan('combined'));
+
+// Add the code below 👇
+app.use(auth({
+ auth0Logout: true,
+ baseURL: appUrl
+}));
+
+// ... other app routes
+```
+
+The middleware you installed automatically defines three routes in your application:
+
+- `/login` - builds the OpenID Connect request and redirects to the authorization server (in this case, Auth0). For this to work properly, the middleware needs to include specific parameters with the request. You will configure these values using environment variables in the next step.
+- `/callback` - handles the response from the authorization server, performs required validations like nonce, state, and token verification using the `openid-client` package, and sets the user in the session from the ID token claims.
+- `/logout` - terminates the session in the application and redirects to Auth0 to end the session there as well.
+
+The middleware will also augment Express’s request object with additional properties whenever the request is authenticated. For example, `req.openid.user` is a property that will contain user information.
+
+::: note
+The `auth0Logout: true` configuration key passed to `auth()` tells the middleware that, when the user logs out of the application, they should be redirected to a specific Auth0 URL to end their session there as well.
+:::
+
+The middleware needs to be initialized with some information to build a proper OpenID request and send it to the authorization server. This information includes:
+
+- **The URL of the authorization server.** This URL will be used to download the OpenID Connect configuration from the discovery document, available at the URL `https://{your-auth0-domain}/.well-known/openid-configuration` ([here is the configuration](https://auth0.auth0.com/.well-known/openid-configuration) for the main Auth0 tenant). The discovery document is a standard OpenID Connect mechanism used to publish relevant discovery metadata of the OpenID Connect provider, including a link to what keys should be used for validating the tokens it issues.
+- **The unique identifier for your application.** This is created on the authorization server and is a unique string that identifies your application. This identifier must be provided in each request, so the authorization server knows what application the authentication request is for.
+
+You will use the Auth0 Dashboard to register your application with Auth0. Afterward, you’ll be able to retrieve the two values above and configure them as environment variables for your app. The middleware will read these environment variables and use them to build the request when a user tries to authenticate.
+
+9. Log into the Auth0 Dashboard, go to the [Applications page](${manage_url}/#/applications), and click the **Create Application** button.
+
+10. Set a descriptive name (e.g., "Identity Lab 1 - Web Sign In"), choose **Regular Web Applications** for the type, and click **Create**.
+
+11. You should now see the Quickstart section that describes how to integrate Auth0 with a production application. Click the **Settings** tab at the top to see the Application settings.
+
+12. Add your application’s callback URL - `http://localhost:3000/callback` (adjust the port number if needed) - to the **Allowed Callback URLs** field. Auth0 will allow redirects **only** to the URLs in this field after authentication. If the one provided in the authorization URL does not match any in this field, an error page will be displayed.
+
+
+
+13. Next, add `http://localhost:3000` (adjust the port number if needed) to the **Allowed Logout URLs field**. Auth0 will allow redirects **only** to the URLs in this field after logging out of the authorization server.
+
+
+
+14. Scroll down and click **Show Advanced Settings**, then **OAuth**. Make sure **JsonWebToken Signature Algorithm** is set to `RS256`.
+
+15. Scroll down and click **Save Changes**
+
+16. Open your `.env` file. Add `https://` to the **Domain** from Auth0 as the value for the `ISSUER_BASE_URL` key. Add the **Client ID** from Auth0 as the value for the `CLIENT_ID` key. Add a long, random string and the value for the `APP_SESSION_SECRET` key. You `.env` file should look similar to the sample below:
+
+```
+ISSUER_BASE_URL=https://your-tenant-name.auth0.com
+CLIENT_ID=0VMFtHgN9mUa1YFoDx3CD2Qnp2Z11mvx
+APP_SESSION_SECRET=a36877de800e31ba46df86ec947dab2fc8a2f7e1d23688ce2010cd076539bd28
+PORT=3000
+```
+
+::: note
+Mac users can enter the following in Terminal to get a random string suitable for the secret value: `openssl rand -hex 32`. This value is used by the session handler in the SDK to generate opaque session cookies.
+:::
+
+17. Save the changes to `.env` and restart the server as before, but do not open it in a browser yet.
+
+Your app is now ready to authenticate with Auth0 using OpenID Connect! Before testing it, continue to the next exercise, where you will review the interactions that happen under the hood between your app and Auth0 while you sign up and log in.
+
+```bash
+# Continuing from previous terminal session ...
+listening on http://localhost:3000
+^C # Command to stop the server
+❯ npm start
+
+listening on http://localhost:3000
+```
+
+
+
+
+Next →
diff --git a/articles/identity-labs/01-web-sign-in/exercise-02.md b/articles/identity-labs/01-web-sign-in/exercise-02.md
new file mode 100644
index 0000000000..1d5d2759a4
--- /dev/null
+++ b/articles/identity-labs/01-web-sign-in/exercise-02.md
@@ -0,0 +1,133 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 1, Exercise 2: Using Network Traces
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 1, Exercise 2: Using Network Traces
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/01-web-sign-in) and read through the instructions before getting started.
+:::
+
+In this exercise, you will sign up for your application (which will also log you in) while exploring some of the relevant network traces of the authentication process.
+
+
+
+1. Using Chrome, open **Developer Tools**. Switch to the **Network** tab then open your local application. You should immediately be redirected to Auth0 to login.
+
+2. The first request you should see is a GET request to your application homepage:
+
+
+
+3. After that, you should see a GET request to `https://your-tenant-name.auth0.com/authorize`. This is the middleware added in exercise 1 taking over. The middleware checks if the user is logged in and, because they are not, it builds the OpenID Connect request to the authorization server URL and forwards the user to it. In this case, the complete GET request URL will look something like this (line breaks added for clarity):
+
+```text
+https://YOUR_DOMAIN/authorize
+?client_id=YOUR_CLIENT_ID
+&scope=openid%20profile%20email
+&response_type=id_token
+&nonce=71890cc63567e17b
+&state=85d5152581b310e3389b
+&redirect_uri=http%3A%2F%2Flocalhost%3A3000
+&response_mode=form_post
+```
+
+---
+
+The middleware sends several parameters. The important ones for this lab are:
+
+- `client_id`: the unique identifier of your app at the authorization server
+- `response_type`: the requested artifacts; in this case, you are requesting an ID token
+- `scope`: why the artifacts are required, i.e. what content and capabilities are needed
+- `redirect_uri`: where the results are to be sent after the login operation, i.e. the callback URL.
+- `response_mode`: how the response from the server is to be sent to the app; in this case, the response we want is a POST request.
+
+
+
+::: note
+If you scroll down while on the **Headers** tab in Chrome Developer Tools to the **Query String Parameters** section, you can see the different URL parameters in a more-readable table format.
+:::
+
+4. If you already have a user created, enter your credentials and continue below. If not, click the **Sign Up** link at the bottom (if you're using the classic page, this will be a tab at the top) and enter an email and password.
+
+5. A consent dialog will be shown requesting access to your profile and email. Click the green button to accept and continue.
+
+6. The authorization server will log you in and POST the response - an error if something went wrong or the ID token if not - back to the callback URL for your application. Once you’ve successfully logged in, you should see your user name on the page. This means authentication has been configured properly!
+
+
+
+The complete trace of the callback request is:
+
+```text
+Request URL: `http://localhost:3000/callback`
+Request Method: POST
+Status Code: 302 Found
+Remote Address: [::1]:3000
+Referrer Policy: no-referrer-when-downgrade
+Connection: keep-alive
+Content-Length: 46
+Content-Type: text/html; charset=utf-8
+Date: Mon, 12 Nov 2018 23:00:08 GMT
+Location: /
+Set-Cookie: identity102-lab=eyJyZX[..]; path=/; httponly
+Set-Cookie: identity102-lab.sig=wld5z7[..]; path=/; httponly
+Vary: Accept
+X-Powered-By: Express
+id_token: eyJ0eX[..].eyJuaW[..].IEpcS5[..]
+state: 85d5152581b310e3389b
+```
+
+::: note
+If you see an error in your console about an ID token used too early, this is likely a clock skew issue in your local environment. Try restarting your machine and walking through the login steps again from the beginning.
+:::
+
+7. Click on the callback request, then search for the Form Data section of the Headers tab of the Developer Console. Copy the complete `id_token` value.
+
+
+
+8. Go to [jwt.io](https://jwt.io) and paste the ID token copied from the last step into the text area on the left. Notice that as soon as you paste it, the contents of the text area on the right are updated. This is because the site decodes your ID token and displays its contents (claims) in that panel.
+
+
+
+Note the following:
+
+- The token structure: it consists of the header (information about the token), the payload (the token’s claims and user profile information), and the signature.
+- The claim `iss` is for the issuer of the token. It denotes who created and signed it. The value should match your Auth0 Domain value with an `https://` prefixed.
+- The claim `sub` is the subject of the token. It denotes to whom the token refers. In our case, the value matches the ID of the Auth0 user.
+- The claim `aud` is the audience of the token. It denotes for which app the token is intended. In our case, this matches the Client ID of the application that made the authentication request.
+- The claim `iat` shows when the token was issued (seconds since Unix epoch) and can be used to determine the token’s age.
+- The claim `exp` shows when the token expires (seconds since Unix epoch).
+
+🎉 **You have completed Lab 1 by building a web application with sign-on using OpenID Connect!** 🎉
+
+
+
+
+
+← All Identity Labs
diff --git a/articles/identity-labs/01-web-sign-in/index.md b/articles/identity-labs/01-web-sign-in/index.md
new file mode 100644
index 0000000000..54291adf62
--- /dev/null
+++ b/articles/identity-labs/01-web-sign-in/index.md
@@ -0,0 +1,39 @@
+---
+section: exercises
+classes: topic-page
+description: Auth0 digital identity Lab 1: Web Sign-In
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 1: Web Sign-In
+
+This lab covers the process for adding sign-in to a basic Node.js application. This lab is the same exercise we provide for new employees in a technical role here at Auth0.
+
+::: warning
+The Node OIDC npm package that this lab uses has not been tested, licensed, or officially released and should not be used in production.
+:::
+
+## Prerequisites
+
+- Read the introduction on the [main Identity Labs page](/identity-labs)
+- Watch the [Introduction to Identity video](/videos/learn-identity/01-introduction-to-identity)
+- Watch the [OIDC and OAuth video](/videos/learn-identity/02-oidc-and-oauth)
+- Watch the [Web Sign-In video](/videos/learn-identity/03-web-sign-in)
+- Read [Using Express Middleware](https://expressjs.com/en/guide/using-middleware.html) (optional)
+- Read [Beginner's Guide to Using npm](https://nodesource.com/blog/an-absolute-beginners-guide-to-using-npm/) (optional)
+
+## What You'll Need
+
+<%= include('../_includes/_what-you-need') %>
+
+---
+
+**For Windows users** - We recommend that you use the Windows PowerShell terminal (instead of the Windows command line) so that the terminal commands provided in the lab instructions work as they are. This is because the syntax of the commands used in the labs is the same for the Mac and PowerShell terminals.
+
+Start →
diff --git a/articles/identity-labs/02-calling-an-api/exercise-01.md b/articles/identity-labs/02-calling-an-api/exercise-01.md
new file mode 100644
index 0000000000..b057e2d5b6
--- /dev/null
+++ b/articles/identity-labs/02-calling-an-api/exercise-01.md
@@ -0,0 +1,216 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 2, Exercise 1: Consuming APIs
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 2, Exercise 1: Consuming APIs
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/02-calling-an-api) and read through the instructions before getting started.
+:::
+
+After learning how to secure your web application with Auth0 in [lab 1](/identity-labs/01-web-sign-in), you will now learn how to make this application consume APIs on behalf of your users. You will start by running an unsecured API and a web application to see both working together, and then you will secure your API with Auth0.
+
+
+
+1. Open a new terminal and browse to `/lab-02/begin/api` in your locally-cloned copy of the [identity exercise repo](https://github.com/auth0/identity-102-exercises/). This is where the code for your API resides. The API is an Express backend that contains a single endpoint. This endpoint (served under the root path) returns expenses, which are data that belong to each user (though they are static and the same for all).
+
+<%= include('../_includes/_git-clone-note') %>
+
+2. Install the dependencies using npm:
+
+```bash
+# Make sure we're in the right directory
+❯ pwd
+/Users/username/identity-102-exercises/lab-02/begin/api
+
+❯ npm install
+# Ignore any warnings
+
+added XX packages in X.XXs
+```
+
+3. Next, copy `.env-sample` to `.env` and start the API:
+
+```bash
+❯ cp .env-sample .env
+❯ npm start
+
+listening on http://localhost:3001
+```
+
+::: note
+If you see a message like *Error: listen EADDRINUSE :::3001* in your terminal after starting the application, this means that port 3001 is in use somewhere. Change the `PORT` value in your `.env` file to "3002" and try again.
+:::
+
+4. In a new terminal window or tab, navigate to the `/lab-02/begin/webapp` directory and install the dependencies using npm:
+
+```bash
+# Navigating from the previous directory
+❯ cd ../webapp
+
+# Make sure we're in the right directory
+❯ pwd
+/Users/username/identity-102-exercises/lab-02/begin/webapp
+
+❯ npm install
+# Ignore any warnings
+
+added XX packages in X.XXs
+```
+
+5. Once again, copy the `.env-sample` to `.env` for the web application:
+
+```bash
+❯ cp .env-sample .env
+```
+
+6. Update the web application `.env` file you just created with the same values as you used in lab 1. If you did not do lab 1 first, follow steps 9 through 15 [on this page](/identity-labs/01-web-sign-in/exercise-01) to create and configure an application with Auth0 and update the `.env` file.
+
+```text
+ISSUER_BASE_URL=https://YOUR_DOMAIN
+CLIENT_ID=YOUR_CLIENT_ID
+API_URL=http://localhost:3001
+PORT=3000
+APP_SESSION_SECRET=LONG_RANDOM_STRING
+```
+
+::: note
+If you changed the port for the API above, make sure to update the `API_URL` with this new value.
+:::
+
+7. Start the web application using npm:
+
+```bash
+❯ npm start
+
+listening on http://localhost:3000
+```
+
+8. Open [localhost:3000](http://localhost:3000) in your browser. There, you will see the homepage of the web application and, if you log in, you will be able to access the expenses report. The page might look similar to the Lab 1 solution, however, the difference is that an external API provides the Expenses information instead of being hard-coded in the Web app.
+
+
+
+Right now, even though the application requires authentication, the API does not. That is, you are calling the API from the Web app, without any authentication information. If you browse to the API's URL at [localhost:3001](http://localhost:3001) without logging in, you will see the expenses. In the following steps, you will update your application to call the API with a token.
+
+9. Open `webapp/server.js` in your code editor and make the following change:
+
+```js
+// webapp/server.js
+
+app.use(auth({
+ required: false,
+ auth0Logout: true,
+ baseURL: appUrl,
+
+ // Add the additional configuration keys below 👇
+ appSessionSecret: false,
+ authorizationParams: {
+ response_type: 'code id_token',
+ response_mode: 'form_post',
+ audience: process.env.API_AUDIENCE,
+ scope: 'openid profile email read:reports'
+ },
+ handleCallback: async function (req, res, next) {
+ req.session.openidTokens = req.openidTokens;
+ req.session.userIdentity = req.openidTokens.claims();
+ next();
+ },
+ getUser: async function (req) {
+ return req.session.userIdentity;
+ }
+ // 👆
+
+}));
+```
+
+This change updates the configuration object passed to `auth()` and defines how you want the `express-openid-connect` library to behave. In this case, you configured the library with a new property called `authorizationParams` and passed in an object with three properties:
+
+- `response_type` - setting this field to `code id_token` indicates that you no longer want the middleware to fetch just an ID token (which is the default behavior for this package). Instead, you are specifying that you want an ID token *and* an authorization code. When you configure the `express-openid-connect` library to fetch an authorization code, the middleware automatically exchanges this code for an access token (this process is known as the Authorization Code Grant flow). Later, you will use the access token to call the API.
+- `response_mode` - This is the same mode used in lab 1, a POST request from the authorization server to the application.
+- `audience` - this tells the middleware that you want access tokens valid for a specific resource server (your API, in this case). As you will see soon, you will configure an `API_AUDIENCE` environment variable to point to the identifier of an API that you will register with Auth0.
+- `scope` - securing your API uses a delegated authorization mechanism where an application (your web app) requests access to resources controlled by the user (the resource owner) and hosted by an API (the resource server). Scopes, in this case, are the permissions that the access token grants to the application on behalf of the user. In your case, you are defining four scopes: the first three (`openid`, `profile`, and `email`) are scopes related to the user profile (part of OpenID Connect specification). The last one, `read:reports`, is a custom scope that will be used to determine whether the caller is authorized to retrieve the expenses report from the API on behalf of a user.
+
+The `appSessionSecret`, `handleCallback`, and `getUser` additions change how the user session is handled and stores the incoming access and refresh tokens somewhere we can access later.
+
+10. Back in the `webapp/server.js` file, find the `/expenses` endpoint definition. In this code, you are making a request to the API, without any authorization information, to get a JSON resource. Note the use of the `requiresAuth()` middleware. This will enforce authentication for all requests to this endpoint.
+
+11. Update the endpoint definition to include authorization information in the request:
+
+```js
+// webapp/server.js
+
+app.get('/expenses', requiresAuth(), async (req, res, next) => {
+ try {
+
+ // Replace this code ❌
+ /*
+ const expenses = await request(process.env.API_URL, {
+ json: true
+ });
+ */
+
+ // ... with the code below 👇
+ let tokenSet = req.openid.makeTokenSet(req.session.openidTokens);
+ const expenses = await request(process.env.API_URL, {
+ headers: { authorization: "Bearer " + tokenSet.access_token },
+ json: true
+ });
+
+ // ... keep the rest
+ }
+ // ...
+});
+```
+
+In the new version of this endpoint, you are sending the access token in an `Authorization` header when sending requests to the API. By doing so, the web application consumes the API on behalf of the logged in user.
+
+12. Add the following two environment variables to the `webapp/.env` file:
+
+```text
+API_AUDIENCE=https://expenses-api
+CLIENT_SECRET=YOUR_APPLICATION_CLIENT_SECRET
+```
+
+The `API_AUDIENCE` value is the identifier for the API that will be created in the following exercise. To get your Client Secret, go to your Application settings page in the Auth0 Dashboard:
+
+
+
+**And that's it!** You have just configured your web application to consume the API on behalf of the logged in user.
+
+If you restart the application in your terminal, logout, and try to log back in, you will see an error because no resource server with the identifier `https://expenses-api` has been registered yet. In the next exercise, you will learn how to create and secure APIs with Auth0, and this request will begin to work.
+
+
+
+
+
+Next →
diff --git a/articles/identity-labs/02-calling-an-api/exercise-02.md b/articles/identity-labs/02-calling-an-api/exercise-02.md
new file mode 100644
index 0000000000..d4ecb91d29
--- /dev/null
+++ b/articles/identity-labs/02-calling-an-api/exercise-02.md
@@ -0,0 +1,144 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 2, Exercise 2: Securing APIs with Auth0
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 2, Exercise 2: Securing APIs with Auth0
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/02-calling-an-api) and read through the instructions before getting started.
+:::
+
+In this exercise, you will register the API with Auth0 so that tokens can be issued for it. You will also learn how to secure your API with Auth0. You will refactor the API that your web application is consuming by installing and configuring some libraries needed to secure it with Auth0.
+
+
+
+1. To register the API with Auth0, open the Auth0 Dashboard and go to the [APIs screen](${manage_url}/#/apis).
+
+2. Click the **Create API** button. Add a descriptive Name, paste `https://expenses-api` into the **Identifier** field, and click **Create**.
+
+3. Click the **Permissions** tab and add a new permission called `read:reports` with a suitable description. This custom permission is the one you will use to determine whether the client is authorized to retrieve expenses.
+
+4. In your terminal, restart your web application with `[CTRL]` + `[c]`, then `npm start`.
+
+5. Log out of the web application by clicking [logout](http://localhost:3000/logout), then log in again. When logging in, you will see a consent screen where Auth0 mentions that the web application is requesting access to the read:reports scope:
+
+
+
+6. Agree to this delegation by clicking the **Accept** button, and Auth0 will redirect you back to the application. Now, you should still be able to see your expenses on the expenses page, [localhost:3000/expenses](http://localhost:3000/expenses):
+
+
+
+::: note
+If at any point, you want to see the consent screen again when logging in, you can go to the Users screen in the Auth0 Dashboard, click on the user you'd like to modify, click the **Authorized Applications** tab, find the application you're using, and click **Revoke**. The next time you log in, the consent screen will appear again.
+:::
+
+As mentioned earlier, the expenses API is still not secure. You can see this by navigating directly to [localhost:3001](http://localhost:3001/). The expense data is available publicly, without an access token. The next steps will change the API to require a properly-scoped access token to view.
+
+4. In your terminal, stop your API with `[CTRL]` + `[c]`.
+
+5. Install the `express-oauth2-bearer` npm package. This is an Express authentication middleware used to protect OAuth2 resources, which validates access tokens:
+
+```bash
+# Make sure we're in the right directory
+❯ pwd
+/Users/username/identity-102-exercises/lab-02/begin/api
+
+❯ npm install express-oauth2-bearer@0.4.0 --save
+# Ignore any warnings
+
++ express-oauth2-bearer@0.4.0
+added XX packages in X.XXs
+```
+
+6. Open the `api/api-server.js` file and add a statement to import the library. Make sure this is added after the dotenv require statement:
+
+```js
+// api/api-server.js
+
+require('dotenv').config();
+// ... other require statements
+
+// Add the line below 👇
+const { auth, requiredScopes } = require('express-oauth2-bearer');
+```
+
+7. Configure the Express app to use the authentication middleware for all requests:
+
+```js
+// api/api-server.js
+
+// ... other require statements
+const app = express();
+
+// Add the line below 👇
+app.use(auth());
+```
+
+8. Find the `/` endpoint code and update it to require the `read:reports` scope in access tokens. This is done by adding a `requiredScopes` middleware, as shown below:
+
+```js
+// lab-02/begin/api/api-server.js
+
+// Change only the line below 👇
+app.get('/', requiredScopes('read:reports'), (req, res) => {
+
+ // ... leave the endpoint contents unchanged.
+
+});
+```
+
+The next time you run your API, all requests that do not include a valid access token (expired token, incorrect scopes, etc.) will return an error instead of the desired data.
+
+9. Open the `api/.env` file you created before and change the `ISSUER_BASE_URL` value to your own Auth0 base URL (same as the one in your application). The `.env` file should look like this:
+
+```text
+PORT=3001
+ISSUER_BASE_URL=https://your-tenant-name.auth0.com
+ALLOWED_AUDIENCES=https://expenses-api
+```
+
+10. Once again, start the API server with npm:
+
+```bash
+❯ npm start
+
+listening on http://localhost:3001
+```
+
+To test your secured API, refresh the expenses page in your application - [localhost:3000/expenses](http://localhost:3000/expenses). If everything works as expected, you will still be able to access this view (which means that the web app is consuming the API on your behalf). If you browse directly to the API at [localhost:3001](http://localhost:3001), however, you will get an error saying the token is missing.
+
+
+
+
+
+Next →
diff --git a/articles/identity-labs/02-calling-an-api/exercise-03.md b/articles/identity-labs/02-calling-an-api/exercise-03.md
new file mode 100644
index 0000000000..7d0c5c465e
--- /dev/null
+++ b/articles/identity-labs/02-calling-an-api/exercise-03.md
@@ -0,0 +1,140 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 2, Exercise 3: Working with Refresh Tokens
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 2, Exercise 3: Working with Refresh Tokens
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/02-calling-an-api) and read through the instructions before getting started.
+:::
+
+
+
+Right now, if your users stay logged in for too long and try to refresh the `/expenses` page, they will face a problem. Access tokens were conceived to be exchanged by different services through the network (which makes them more prone to leakage), so they should expire quickly. When an access token is expired, your API won't accept it anymore, and your web application won't be able to fetch the data needed. A token expired error will be returned instead.
+
+To change this behavior, you can make your web app take advantage of yet another token: the refresh token. A refresh token is used to obtain new access tokens and/or ID tokens from the authorization server. In this exercise, we're going to modify the application to obtain a refresh token and use it to get a new access token when it expires.
+
+1. Navigate to the [APIs screen](${manage_url}/#/apis) in your Auth0 Dashboard and open the API created in the last exercise. Scroll down, turn on the **Allow Offline Access** option, and click **Save**:
+
+
+
+2. Now, Open the `webapp/server.js` file and add `offline_access` to the `authorizationParams.scope` field passed to the `auth()` middleware:
+
+```js
+// webapp/server.js
+
+app.use(auth({
+ required: false,
+ auth0Logout: true,
+ appSessionSecret: false,
+ authorizationParams: {
+ response_type: 'code id_token',
+ response_mode: 'form_post',
+ audience: process.env.API_AUDIENCE,
+
+ // Change only the line below 👇
+ scope: 'openid profile email read:reports offline_access'
+
+ },
+
+ // ... keep the rest
+
+}));
+```
+
+3. Now, find the following line in the `/expenses` endpoint code and replace it with the following:
+
+```js
+// webapp/server.js
+
+app.get('/expenses', requiresAuth(), async (req, res, next) => {
+ try {
+
+ let tokenSet = req.openid.makeTokenSet(req.session.openidTokens);
+
+ // Add the code block below 👇
+ if (tokenSet.expired()) {
+ tokenSet = await req.openid.client.refresh(tokenSet);
+ tokenSet.refresh_token = req.session.openidTokens.refresh_token;
+ req.session.openidTokens = tokenSet;
+ }
+
+ // ... keep the rest
+ }
+ // ...
+});
+```
+
+This change will update your endpoint to check if the `tokenSet` is expired. If it is, the `Issuer` class will create a client that is capable of refreshing the `tokenSet`. To see the refreshing process in action, you will have to make a small change to your Auth0 API configuration.
+
+4. Navigate to the [APIs screen](${manage_url}/#/apis) in your Auth0 Dashboard and open the API created in the last exercise. Set both the **Token Expiration (Seconds)** and **Token Expiration For Browser Flows (Seconds)** values to 10 seconds or less and click **Save**:
+
+
+
+5. Back in your editor, add a log statement to `api/api-server.js` to show when the new access token was issued:
+
+```js
+// api/api-server.js
+
+app.get('/', requiredScopes('read:reports'), (req, res) => {
+
+ // Add the line below 👇
+ console.log(new Date(req.auth.claims.iat * 1000));
+
+ // ...
+});
+```
+
+6. Restart both the application and API (`[CTRL]` + `[c]`, then `npm start`).
+
+7. Log out and log in again. This will get you a complete set of tokens (ID token, access token, and refresh token). Note, at this point, you will see a new consent screen for the offline_access scope, which you need to accept.
+
+Open [localhost:3000/expenses](http://localhost:3000/expenses) in your browser and refresh the page. You will see that your API logs a timestamp in the terminal. The same timestamp will be logged every time you refresh the page as long as your token remains valid. Then, if you wait a few seconds (more than ten) and refresh the view again, you will see that your API starts logging a different timestamp, which corresponds to the new token retrieved. This shows that you are getting a different access token every ten seconds and that your web application uses the refresh token automatically to get them.
+
+::: note
+If you see an error in your console about an ID token used too early, this is likely a clock skew issue in your local environment. Try restarting your machine and walking through the login steps again from the beginning. You can also try going to "Date & Time" settings, unlock them if needed by clicking on the lock icon at the bottom, and disable and re-enable the "Set date and time automatically" option.
+:::
+
+::: note
+If you don't see changes in the "Issued At" claim in the console, make sure you have logged out and logged in again after applying the changes above.
+:::
+
+::: note
+If you are using PowerShell in Windows and you see blank lines instead of the timestamp logging in the terminal, it could be the font color of the logs is the same as the background. As an alternative, you can run the API server from the Windows command line, or change the background color in PowerShell.
+:::
+
+🎉 **You have completed Lab 2 by building a web application that calls an API with refresh capability!** 🎉
+
+
+
+
+
+← All Identity Labs
diff --git a/articles/identity-labs/02-calling-an-api/index.md b/articles/identity-labs/02-calling-an-api/index.md
new file mode 100644
index 0000000000..9b636eda3f
--- /dev/null
+++ b/articles/identity-labs/02-calling-an-api/index.md
@@ -0,0 +1,36 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 2: Calling an API
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 2: Calling an API
+
+This lab covers the process for adding sign-in to a basic Node.js application and calling an API. This lab is the same exercise we provide for new employees in a technical role here at Auth0.
+
+::: warning
+The Node OIDC and bearer token npm packages that this lab uses has not been tested, licensed, or officially released and should not be used in production.
+:::
+
+## Prerequisites
+
+- Read the introduction on the [main Identity Labs page](/labs/)
+- Watch the [Calling an API video](/videos/learn-identity/04-calling-an-api)
+- Read [Using Express Middleware](https://expressjs.com/en/guide/using-middleware.html) (optional)
+- Read [Beginner's Guide to Using npm](https://nodesource.com/blog/an-absolute-beginners-guide-to-using-npm/) (optional)
+
+## What You'll Need
+
+<%= include('../_includes/_what-you-need') %>
+
+---
+
+**For Windows users** - We recommend that you use the Windows PowerShell terminal (instead of the Windows command line) so that the terminal commands provided in the lab instructions work as they are. This is because the syntax of the commands used in the labs is the same for the Mac and PowerShell terminals.
+
+Start →
diff --git a/articles/identity-labs/03-mobile-native-app/exercise-01.md b/articles/identity-labs/03-mobile-native-app/exercise-01.md
new file mode 100644
index 0000000000..eddea08b18
--- /dev/null
+++ b/articles/identity-labs/03-mobile-native-app/exercise-01.md
@@ -0,0 +1,274 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 3, Exercise 1: Adding Authentication
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 3, Exercise 1: Adding Authentication
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/03-mobile-native-app) and read through the instructions before getting started.
+:::
+
+In this exercise, you will add authentication to an existing iOS application. A simple iOS application has been provided to get you started. This is a single-view application with a button to launch the Auth0 authentication process.
+
+
+
+1. Launch Xcode, go to **File > Open**, and open `/lab-03/exercise-01/begin/exercise-01.xcworkspace` in your locally-cloned copy of the [identity exercise repo](https://github.com/auth0/identity-102-exercises/).
+
+<%= include('../_includes/_git-clone-note') %>
+
+::: note
+If the project complains about a missing dependency, you might have opened `exercise-01.xcodeproj` instead of `exercise-01.xcworkspace` (note the extension).
+:::
+
+This project is a bare-bones application that imports the [Auth0.swift](https://github.com/auth0/auth0.swift) dependency to provide the OpenID Connect implementation. There is also a stub method called `actionLogin` for processing the touch of the login button.
+
+2. In the bar at the top of the project window, click the device selector and pick a late-model iPhone, then click the Play button (or **Product > Run** from the Xcode menu) to run the app.
+
+
+
+The simulator may take a few moments to load the first time, and then you should see the following:
+
+
+
+3. Touch the **Log In** button. This will output a "Log In" message to the Debug area in Xcode. If you don’t see the Debug view, you can enable it with **View > Debug Area > Show Debug Area**.
+
+
+
+4. Before any calls are made to the Auth0 authorization server, you need to set up a new Auth0 Application for handling Native Applications. Log into the Auth0 Dashboard, go to the [Applications page](${manage_url}/#/applications), and click the **Create Application** button.
+
+5. Enter a descriptive name, select **Native** as the application type, and click **Create**.
+
+6. Click on the **Settings** tab and scroll down to the **Allowed Callback URLs** field. Enter the value below (modified with your tenant domain):
+
+```text
+com.auth0.identity102://${account.namespace}/ios/com.auth0.identity102/callback
+```
+
+7. Scroll down and click **Show Advanced Settings**, then **OAuth**. Make sure **JsonWebToken Signature Algorithm** is set to `RS256`.
+
+8. Click **Save Changes**
+
+You might be wondering why the callback URL is in this format. There are two parts to this:
+
+- The first element is the scheme of the application, which for the purposes of this exercise, is defined as `com.auth0.identity102`. Whenever Safari needs to handle a request with this scheme, it will route it to our application (you will set up this custom URL scheme URL later in the lab).
+- The rest of the URL is in a format that the Auth0.swift SDK specifies for callbacks.
+
+9. Now the sample iOS application needs to be configured with the **Client ID** and **Domain** values from the Auth0 Application. Return to Xcode and open the `exercise-01/Auth0.plist` file. You should see value placeholders for **ClientId** and **Domain**. Replace these with the values from the Auth0 Application created above.
+
+
+
+::: note
+The domain must not have any prefix like in the previous labs. Enter it exactly as it is provided in the Auth0 dashboard.
+:::
+
+To be able to use the callback that was configured in the Auth0 dashboard, a URL scheme handler needs to be registered in our iOS application so that it can respond to requests made to the callback URL.
+
+10. In the file navigator on the left, click on `exercise-01` to open the project settings, then click on the **Info** tab.
+
+
+
+11. Scroll down to **URL Types**, expand the section, click the **+** button, and enter or select the following details:
+
+- **Identifier**: `auth0`
+- **URL Schemes**: `$(PRODUCT_BUNDLE_IDENTIFIER)`
+- **Role**: `None`
+
+Just as `http` is a URL Scheme that will launch a browser, the bundle identifier of the app has a URL Scheme (which will resolve to `com.auth0.identity102`) will tell iOS that any time this scheme is used in a URL, it must be routed to our application. That will be the case of the callback used by Auth0 after you log in.
+
+12. Now, the application needs to have the Auth0.swift SDK handle the callback in order to proceed with the authentication flow. In the Project Navigator on the left, open `exercise-01/AppDelegate.swift` and add the following import statement just below the other one:
+
+```swift
+// exercise-01/AppDelegate.swift
+
+import UIKit
+
+// Add the line below 👇
+import Auth0
+```
+
+13. In the same file, add the following method inside the `AppDelegate` class:
+
+```swift
+// exercise-01/AppDelegate.swift
+// ...
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+ var window: UIWindow?
+
+ // Add the code below 👇
+ func application(_
+ app: UIApplication,
+ open url: URL,
+ options: [UIApplication.OpenURLOptionsKey : Any]
+ ) -> Bool {
+ return Auth0.resumeAuth(url, options: options)
+ }
+
+ // ... other existing methods
+}
+```
+
+When another app requests a URL containing the custom scheme, the system will launch your app if necessary, bring it to the foreground, and call the method above. The iOS Framework provides the delegate method above for you to implement so that you can parse the contents of the URL and take appropriate action. In this case, you need this information to continue the authentication flow process. You will see later in this exercise why this step is needed.
+
+Now that the iOS application is configured with your Auth0 application credentials and is able to receive and process callbacks, complete the following steps to see how to construct the OpenID Connect request to the authorization server.
+
+14. Open `exercise-01/ViewController.swift` and add the following code inside the `actionLogin` method, after the line that prints the "Log In" message to the console:
+
+```swift
+// exercise-01/ViewController.swift
+// ...
+ @IBAction func actionLogin(_ sender: Any) {
+ print("Log In")
+
+ // Add the code below 👇
+ Auth0
+ .webAuth()
+ .scope("openid profile email")
+ .logging(enabled: true)
+ .start { response in
+ switch(response) {
+ case .success(let result):
+ print("Authentication Success")
+ print("Access Token: \(result.accessToken ?? "No Access Token Found")")
+ print("ID Token: \(result.idToken ?? "No ID Token Found")")
+ case .failure(let error):
+ print("Authentication Failed: \(error)")
+ }
+ }
+ }
+// ...
+```
+
+15. Run the app again by clicking the Play button (or **Product > Run** from the Xcode menu). Once the app has launched, touch the **Log In** button. You should see a permission prompt from iOS. Touch **Continue** to proceed to the Auth0 login page, which is rendered within a browser.
+
+
+
+16. Log in using your database user, and you will be taken back to the app. Nothing will have changed visually, but if you take a look at the Debug Area in Xcode you will see something like this:
+
+```text
+Authentication Success
+Access Token: vxPp0Xtg3wkZJudFZWzqMQByYF98Qyer
+ID Token: eyJ0eX[..].eyJodH[..].kLtZDg[..]
+```
+
+To view the contents of your ID Token, you can copy and paste it into [jwt.io](https://jwt.io/) to view the claims.
+
+Now that you have an ID token, it's important to validate it to ensure that it can be trusted. A helper method `isTokenValid` is already included in the project; you can review its code in `Extras/Utils.swift` to learn how the validation is performed. It should be called after obtaining the token, to illustrate how it is used.
+
+17. Back in the `actionLogin` method in `ViewController.swift`, add the line below:
+
+```swift
+// exercise-01/ViewController.swift
+// ...
+
+ @IBAction func actionLogin(_ sender: Any) {
+ print("Log In")
+
+ Auth0
+ // ...
+ case .success(let result):
+ // ... other print statements
+
+ // Add the line below 👇
+ print("ID Token Valid: \(isTokenValid(result.idToken!))")
+
+ // ... failure case
+ }
+ }
+// ...
+```
+
+18. Run the app again, log in, and take a look at the logs in Xcode. You should see an entry "ID Token Valid:" with the status of the validation (true or false).
+
+Congratulations! You have successfully added Auth0 authentication to your native iOS app using an authorization code grant!
+
+The authorization code grant by itself has some security issues when implemented on native applications. For instance, a malicious attacker can intercept the authorization code returned by Auth0 and exchange it for an access token. The Proof Key for Code Exchange (PKCE) is a technique used to mitigate this authorization code interception attack.
+
+With PKCE, for every authorization request, the application creates a cryptographically random key called the **code verifier**, hashes that value into a **code challenge**, and sends the **code challenge** to the authorization server to get the authorization code. When the application receives the code after a successful login, it will send the code and the code verifier to the token endpoint to exchange them for the requested tokens.
+
+Since you previously enabled logging in our `WebAuth` call with the `logging()` method, it is easy to see the process flow in the Debug Area.
+
+19. Run the iOS Application, touch the **Log In** button, and then take a look at the Debug Area. The iOS application initiates the flow and redirects the user to the `/authorize` endpoint, sending the `code_challenge` and `code_challenge_method` parameters. It also sends a `response_type` of `code` (line breaks added below for readability):
+
+```text
+SafariAuthenticationSession:
+https://${account.namespace}/authorize
+?code_challenge=VsPaQ0gJjnluA2vwV0piY-D-DTCltGI9GbYkBNHvPHQ
+&response_type=code
+&redirect_uri=com.auth0.identity102://${account.namespace}/ios/com.auth0.identity102/callback
+&state=RFnNyPj4NOZMUW8IpDBr-j3UgO4gCbhBZtLpWB_vmDo
+&client_id=${account.clientId}
+&scope=openid%20profile
+&code_challenge_method=S256
+&auth0Client=eyJzd2lmdC12ZXJzaW9uIjoiMy4wIiwibmFtZSI6IkF1dGgwLnN3aWZ0IiwidmVyc2lvbiI6IjEuMTMuMCJ9
+```
+
+20. Once again, enter your credentials and log in. Auth0 redirects the user back to the iOS application by calling the callback with the authorization code in the query string:
+
+```text
+iOS Safari:
+com.auth0.identity102://${account.namespace}/ios/com.auth0.identity102/callback
+?code=6SiMHrJHbG2aAPrj
+&state=RFnNyPj4NOZMUW8IpDBr-j3UgO4gCbhBZtLpWB_vmDo
+```
+
+21. The Auth0.swift SDK will process the query string and send the authorization `code` and `code_verifier` together with the `redirect_uri` and the `client_id` to the token endpoint of the authorization server:
+
+```text
+POST /oauth/token
+
+{"grant_type":"authorization_code",
+"redirect_uri":"com.auth0.identity102:\/\/${account.namespace}\/ios\/com.auth0.identity102\/callback",
+"code":"6SiMHrJHbG2aAPrj",
+"code_verifier":"qiV8gYUrPco3qBlejLeZzgC9DMtXZY1GddzZpmVxyxw",
+"client_id":"${account.clientId}"}
+```
+
+22. The authorization server validates this information and returns the requested access and ID tokens. If successful, you will see the following response containing your tokens:
+
+```text
+Content-Type: application/json
+
+{"access_token":"ekhGPSE7xdhOTJuTo2dV-TYyJV-OTYrO",
+"id_token":"eyJ0eX[..].eyJodH[..].1kZccn[..]",
+"expires_in":86400,
+"token_type":"Bearer"}
+```
+
+In the next exercise, you will use a token to validate and authorize the user and authorize against a protected API.
+
+
+
+
+
+Next →
diff --git a/articles/identity-labs/03-mobile-native-app/exercise-02.md b/articles/identity-labs/03-mobile-native-app/exercise-02.md
new file mode 100644
index 0000000000..c0a673e7d9
--- /dev/null
+++ b/articles/identity-labs/03-mobile-native-app/exercise-02.md
@@ -0,0 +1,340 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 3, Exercise 2: Calling a Secured API
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - concept
+---
+# Lab 3, Exercise 2: Calling a Secured API
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/03-mobile-native-app) and read through the instructions before getting started.
+:::
+
+In this exercise, you are going to enable the native application to authorize against the protected API backend that was built in [Lab 2, Exercise 2](/identity-labs/02-calling-an-api/exercise-02). In that lab, you set up an Auth0 API server for your Expenses API with an audience value of `https://expenses-api`.
+
+
+
+
+If you have already completed lab 2, you can use the same Auth0 configuration and local files to run the API needed for this lab. Just go to `/lab-02/begin/api` in your locally-cloned copy of the [identity exercise repo](https://github.com/auth0/identity-102-exercises/) and run `npm start` in your terminal before beginning this exercise. Make sure your token expiration times in Auth0 are back to normal (at least an hour for both).
+
+::: panel If you did not complete Lab 2
+If you are doing this lab by itself, you can use the completed exercise sample code:
+
+1. Go to `/lab-02/end/api` and run `npm install` in your terminal.
+
+2. Follow steps 1-3 on [this page](/identity-labs/02-calling-an-api/exercise-02) to create an API in Auth0.
+
+3. Create a copy of the `.env` file in the same directory as above, change the `ISSUER_BASE_URL` value to include your tenant name, and save the file.
+
+4. Back in the terminal, run `npm start`.
+
+```bash
+# Starting from the Lab 3 begin folder...
+❯ cd ../../../lab-02/end/api
+
+❯ pwd
+/Users/username/identity-102-exercises/lab-02/end/api
+
+❯ cp .env-sample .env
+
+❯ vim .env
+# Change the ISSUER_BASE_URL value ...
+
+❯ npm install
+
+added XX packages in X.XXs
+
+❯ npm start
+
+listening on http://localhost:3001
+```
+
+:::
+
+Regardless of which API codebase you're using, you should now be able to load [localhost:3001](http://localhost:3001/) in your browser and see an error saying `UnauthorizedError: bearer token is missing`.
+
+5. For this exercise, we're going to open a different project in Xcode than the one we used in exercise 1. Go to **File > Open** in Xcode and select `lab-03/exercise-02/begin/exercise-02.xcworkspace` (make sure you pick the right file extension), then open `exercise-02/ViewController.swift`. This code picks up where the previous exercise left off and adds a new button to call the API.
+
+6. Open the `exercise-02/Auth0.plist` file and replace the placeholder values for **ClientId** and **Domain** with the ones from the Auth0 Application created before.
+
+7. Click the Play button (or **Product > Run** from the Xcode menu) to run the app.
+
+
+
+8. Touch the **Call API** button, and you should see a "Call API" message in the Debug area in Xcode.
+
+
+
+You will now add code to make the API call from the mobile app. However, before doing so, you need to modify the authentication code to include the API's audience for authorization and the necessary scopes so that the required permissions are requested.
+
+9. In the `actionLogin` method, which contains our authentication call, include the audience for the API we want to access. With this in place, there will be an additional audience inside the access token after successful authentication.
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+
+ @IBAction func actionLogin(_ sender: Any) {
+ Auth0
+ .webAuth()
+ .scope("openid profile")
+
+ // Add the line below 👇
+ .audience("https://expenses-api")
+
+ // ...
+ }
+ }
+// ...
+```
+
+10. Run the app from Xcode again, click **Log In**, and check the debug logs. You should see a block of output like below:
+
+```text
+Authentication Success
+Access Token: eyJ0eXA[..].eyJpc3[..].XeiZaS[..]
+ID Token: eyJ0eXA[..].eyJodH[..].Lv1TY8[..]
+Token Valid: true
+```
+
+11. Copy and paste the value of the **Access Token** into [jwt.io](https://jwt.io). Notice the `scope` value of `openid profile`. In Lab 2, the additional scope `read:reports` was added, which is not present in the token yet:
+
+```js
+{
+ "iss": "https://${account.namespace}/",
+ "sub": "auth0|1234567890",
+ "aud": [
+
+ // New audience 👇
+ "https://expenses-api",
+ "https://${account.namespace}/userinfo"
+ ],
+ "iat": 1566840738,
+ "exp": 1566840746,
+ "azp": "${account.clientId}",
+
+ // Existing scopes 👇
+ "scope": "openid profile"
+}
+```
+
+12. Now, add the `read:reports` scope to the parameter in the `scope()` method within `actionLogin`:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+
+ @IBAction func actionLogin(_ sender: Any) {
+ Auth0
+ .webAuth()
+
+ // Replace this line ❌
+ // .scope("openid profile")
+
+ // ... with the line below 👇
+ .scope("openid profile read:reports")
+
+ // ...
+ }
+ }
+```
+
+13. Run the app again, log in, and check the access token in [jwt.io](https://jwt.io) once more. You should now see the `read:reports` scope in the payload. It’s time to make a call to the API!
+
+14. To use the access token we obtained during login in the `actionAPI` method, you need a way to access this variable. Create a private variable in the `ViewController` class:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+import Auth0
+
+class ViewController: UIViewController {
+
+ // Add the line below 👇
+ private var accessToken: String?
+
+ // ...
+}
+```
+
+15. In the `.success` code block of the `actionLogin` method, set the new `accessToken` value to be what was returned from the token endpoint:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+ @IBAction func actionLogin(_ sender: Any) {
+ // ...
+ case .success(let result):
+ // ...
+
+ // Add the line below 👇
+ self.accessToken = result.accessToken
+
+ case .failure(let error):
+ // ...
+ }
+// ...
+```
+
+16. In the `actionAPI` method in the same class, check that the user has authenticated and that you have an access token before making a call to the API:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+ @IBAction func actionAPI(_ sender: Any) {
+ print("Call API")
+
+ // Add the code below 👇
+ guard let accessToken = self.accessToken else {
+ print("No Access Token found")
+ return
+ }
+ }
+// ...
+```
+
+Here, you are assigning the class-scoped property `accessToken` to a local `accessToken` variable. If the class-scoped property is empty, an error will be returned.
+
+17. Again in the `actionAPI` method, add the code below to start an API request:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+ @IBAction func actionAPI(_ sender: Any) {
+ // ... code from above
+
+ // Add the code below 👇
+ let url = URL(string: "http://localhost:3001")!
+ var request = URLRequest(url: url)
+ }
+// ...
+```
+
+::: note
+If your API is running on a different port or URL, make sure to change that above.
+:::
+
+18. You also need a way to send the access token to the API. This is done by adding an HTTP Authorization request header:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+ @IBAction func actionAPI(_ sender: Any) {
+ // ... code from above
+
+ // Add the code below 👇
+ request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
+ request.log()
+ }
+// ...
+```
+
+19. Finally, the request needs to be executed. You will use the functionality built into the iOS framework - `URLSession` - to perform the network operation:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+ @IBAction func actionAPI(_ sender: Any) {
+ // ... code from above
+
+ // Add the code below 👇
+ let task = URLSession.shared.dataTask(with: request) {
+ data, response, error in
+ print(response ?? "No Response")
+ }
+ task.resume() // Execute the request
+ }
+// ...
+```
+
+20. Let's try calling the API from our mobile app. Save your changes from above, run the app, and tap **Log In**. After successfully authenticating, tap the **Call API** button and check the logs in the Debug area for the API response:
+
+```text
+Call API
+GET http://localhost:3001
+Headers:
+ Optional(["Authorization": "Bearer eyJ0eX[..].eyJpcM[..].dpN8sK[..]"])
+ { URL: http://localhost:3001/ } { Status Code: 200, Headers {
+ Connection = (
+ "keep-alive"
+ );
+ "Content-Length" = (
+ 195
+ );
+ "Content-Type" = (
+ "application/json; charset=utf-8"
+ );
+ Date = (
+ "Tue, 27 Aug 2019 14:53:40 GMT"
+ );
+ Etag = (
+ "W/\"c3-oBamo6wQLwSzwYwQczXJ+w5tl5o\""
+ );
+ "X-Powered-By" = (
+ Express
+ );
+} }
+```
+
+The `Status Code: 200` (OK) lets us know the request was executed successfully. If you want to see it fail, simply comment out the line that adds the Authorization Bearer header, re-rerun the app, and try logging in again. You will see a `Status Code: 401` (Unauthorized).
+
+21. You can see from the `Content-Length` header that there is a body in the response; output the raw data from the API by updating the `dataTask` closure with the following code:
+
+```swift
+// exercise-02/ViewController.swift
+// ...
+ @IBAction func actionAPI(_ sender: Any) {
+ // ... code from above
+
+ let task = URLSession.shared.dataTask(with: request) {
+ data, response, error in
+ print(response ?? "No Response")
+
+ // Add the code below 👇
+ if let data = data {
+ print(String(data: data, encoding: .utf8) ?? "No Body")
+ }
+ }
+ // ...
+ }
+// ...
+```
+
+22. Re-run the app, login, and call the API once more. You should now see the expenses in the debug area in Xcode:
+
+```js
+[{"date":"2019-08-27T15:02:04.838Z","description":"Pizza for a Coding Dojo session.","value":102},
+{"date":"2019-08-27T15:02:04.838Z","description":"Coffee for a Coding Dojo session.","value":42}]
+```
+
+You have now integrated your native application frontend with a protected API backend! In the next exercise, you will look at how the access token can be refreshed without having the user go through the web-based authentication flow each time.
+
+
+
+
+
+Next →
diff --git a/articles/identity-labs/03-mobile-native-app/exercise-03.md b/articles/identity-labs/03-mobile-native-app/exercise-03.md
new file mode 100644
index 0000000000..1cf3321b8e
--- /dev/null
+++ b/articles/identity-labs/03-mobile-native-app/exercise-03.md
@@ -0,0 +1,232 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 3, Exercise 3: Working with Refresh Tokens
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 3, Exercise 3: Working with Refresh Tokens
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/03-mobile-native-app) and read through the instructions before getting started.
+:::
+
+In this exercise, you will explore the use of refresh tokens. A refresh token is a special kind of token that can be used to obtain a renewed access token. You are able to request new access tokens until the refresh token is blacklisted. It’s important that refresh tokens are stored securely by the application because they essentially allow a user to remain authenticated forever.
+
+
+
+For native applications such as our iOS application, refresh tokens improve the authentication experience significantly. The user has to authenticate only once, through the web authentication process. Subsequent re-authentication can take place without user interaction, using the refresh token.
+
+1. Go to **File > Open** in Xcode and select `lab-03/exercise-03/begin/exercise-03.xcworkspace` (make sure you pick the right file extension), then open `exercise-03/ViewController.swift`. This code picks up where the previous exercise left off and adds a new button to refresh the access token.
+
+2. Open the `exercise-03/Auth0.plist` file and replace the placeholder values for **ClientId** and **Domain** with the ones from the Auth0 Application created before.
+
+3. Click the Play button (or **Product > Run** from the Xcode menu) to run the app. Touch the **Refresh Token** button and look for a “Refresh Token” message to the Debug area in Xcode.
+
+
+
+You are now going to add the `offline_access` scope, which gives the iOS application access to resources on behalf of the user for an extended period of time. Before you can use this scope, you need to make sure that Auth0 will allow applications to ask for refresh tokens for your API.
+
+4. Navigate to the [APIs screen in your Auth0 Dashboard](${manage_url}/#/apis). Open the API that you created to represent your expenses API and ensure the **Allow Offline Access** option is on.
+
+
+
+5. Next, we're going to add the `offline_access` scope to the authentication request. Open `exercise-03/ViewController.swift` and, in the `actionLogin` method, add `offline_access` to the `.scope()` method.
+
+```swift
+// exercise-03/ViewController.swift
+// ...
+ @IBAction func actionLogin(_ sender: Any) {
+ Auth0
+ .webAuth()
+
+ // Replace this line ❌
+ // .scope("openid profile read:reports")
+
+ // ... with the line below 👇
+ .scope("openid profile read:reports offline_access")
+
+ // ...
+ }
+ }
+// ...
+```
+
+6. Click the Play button (or **Product > Run** from the Xcode menu) to run the app. Log in again and check the Debug area in Xcode for the response.
+
+```js
+{
+ "access_token":"3tjDJ3hsFOSyCr02spWHUhHNajxLRonv",
+
+ // Here is the refresh token we asked for 👇
+ "refresh_token":"sAvc4BJyOGs2I6Yc4e6r9NmReLp0kc-I6peiauDEt-usE",
+
+ "id_token": "eyJ0eX[..].eyJodH[..].thhf0M[..]",
+ "expires_in": 86400,
+ "token_type": "Bearer"
+}
+```
+
+7. We're going to send the refresh token to the authorization server using a `refresh_token` grant to get a new access token. In `ViewController.swift` and create a private variable in the `ViewController` class to create a way for `actionRefresh` method to access the refresh token.
+
+```swift
+// exercise-03/ViewController.swift
+// ...
+class ViewController: UIViewController {
+
+ private var accessToken: String?
+
+ // Add the line below 👇
+ private var refreshToken: String?
+
+ // ...
+}
+// ...
+```
+
+8. Assign the refresh token obtained during authentication to this private variable in the `.success` code block.
+
+```swift
+// exercise-03/ViewController.swift
+// ...
+ @IBAction func actionLogin(_ sender: Any) {
+ // ...
+ case .success(let result):
+ // ...
+ self.accessToken = result.accessToken
+
+ // Add the line below 👇
+ self.refreshToken = result.refreshToken
+
+ case .failure(let error):
+ // ...
+ }
+// ...
+```
+
+9. In the `actionRefresh` method, check that the user has authenticated and that a refresh token is available before making any calls to the authentication API. In the code below, the class-scoped property `refreshToken` is assigned to a local `refreshToken` variable. If the class-scoped property is empty, an error will be returned.
+
+```swift
+// exercise-03/ViewController.swift
+// ...
+ @IBAction func actionRefresh(_ sender: Any) {
+ print("Refresh Token")
+
+ // Add the code below 👇
+ guard let refreshToken = self.refreshToken else {
+ print("No Refresh Token found")
+ return
+ }
+ }
+// ...
+```
+
+10. The Auth0.swift SDK makes available a `.renew()` method, which takes a refresh token as a parameter and performs a call to the authorization server's token endpoint using the `refresh_token` grant. Add the following code to the `actionRefresh` method after the code from the previous step.
+
+```swift
+// exercise-03/ViewController.swift
+// ...
+ @IBAction func actionRefresh(_ sender: Any) {
+ // ... code from the previous steps
+
+ // Add the code below 👇
+ Auth0
+ .authentication()
+ .logging(enabled: true)
+ .renew(withRefreshToken: refreshToken)
+ .start { response in
+ switch(response) {
+ case .success(let result):
+ print("Refresh Success")
+ print("New Access Token: \(result.accessToken ?? "No Access Token Found")")
+ self.accessToken = result.accessToken
+ case .failure(let error):
+ print("Refresh Failed: \(error)")
+ }
+ }
+ }
+// ...
+```
+
+11. Click the Play button (or **Product > Run** from the Xcode menu) to re-run the app. Tap **Log In** and, after successful authentication, touch the **Refresh Token** button. Look in the Xcode the debug area for the request. You should see a `POST` to the token endpoint, showing the refresh token grant in action.
+
+```text
+POST https://${account.namespace}/oauth/token HTTP/1.1
+Auth0-Client: eyJuYW1lIjoiQXV0aDAuc3dpZnQiLCJ2ZXJzaW9uIjoiMS4xMy4wIiwic3dpZnQtdmVyc2lvbiI6IjMuMCJ9
+Content-Type: application/json
+
+{"grant_type":"refresh_token","client_id":"${account.clientId}","refresh_token":"2CNxaPe0UIkX_PZkLEkKuoAuRsP6Ycg81XR1jQlTyn1dt"}
+```
+
+12. Look for the response after the request above. You should see a response including a new `access_token`, new `id_token`, and a new `expires_in` time (some of the trace was omitted for brevity).
+
+```text
+HTTP/1.1 200
+Content-Type: application/json
+Date: Tue, 27 Aug 2019 16:25:26 GMT
+x-ratelimit-remaining: 29
+x-ratelimit-reset: 1566923126
+x-ratelimit-limit: 30
+Content-Length: 1923
+
+{"access_token":"eyJ0eX[..].eyJpc3[..].Smqrd7[..]",
+"id_token":"eyJ0eX[..].eyJua[..].Ff5Q5[..]",
+"scope":"openid profile read:reports offline_access",
+"expires_in":3600,"token_type":"Bearer"}
+```
+
+Notice that you don’t receive a new `refresh_token` in the response from the authorization server. The `refresh_token` from the initial authentication must be retained. Also, note that in the code added to the `actionRefresh` method the `access_token` received is stored in the `self.accessToken` class property. This is so the new access token can be used in other methods. If you try calling the API again, the request will be made with your new access_token.
+
+Now that you are able to obtain a fresh access token by using the refresh token, it’s time to see what happens when a token expires.
+
+13. Navigate to the [APIs screen in your Auth0 Dashboard](${manage_url}/#/apis) and open the expenses API. Set both the **Token Expiration** and the **Token Expiration For Browser Flows** fields to 10 seconds and save the changes.
+
+14. In your app simulator, tap **Log In** to walk through the authentication process again and get a new access token with the shorter expiration. Immediately tap the **Call API** button to see the API call succeed.
+
+15. Wait 10 seconds for the token to expire and click the **Call API** button again. You should see the API call fail with a `Status Code: 401` in the debug area.
+
+```text
+ { URL: http://localhost:3001/ } { Status Code: 401, Headers {
+ Date = (
+ "Tue, 27 Aug 2019 16:36:10 GMT"
+ );
+ "www-authentication" = (
+ "Bearer realm=\"api\", error=\"invalid_token\", error_description=\"invalid token\""
+ );
+} }
+```
+
+16. Tap **Refresh Token** and check the debug area to see the refresh token grant happen. Then, tap **Call API**, and you should get a `Status Code: 200` along with the expenses data again.
+
+🎉 **You have completed Lab 3 by building a native mobile application calling a secure API with refresh capability!** 🎉
+
+
+
+
+
+← All Identity Labs
diff --git a/articles/identity-labs/03-mobile-native-app/index.md b/articles/identity-labs/03-mobile-native-app/index.md
new file mode 100644
index 0000000000..f872387025
--- /dev/null
+++ b/articles/identity-labs/03-mobile-native-app/index.md
@@ -0,0 +1,37 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 3: Mobile Native App
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 3: Mobile Native App
+
+## Prerequisites
+
+- Read the introduction on the [main Identity Labs page](/labs/)
+- Watch the [Desktop and Mobile Apps video](/videos/learn-identity/05-desktop-and-mobile-apps)
+- Apple's [Developing iOS Apps: Build a Basic UI](https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/BuildABasicUI.html) tutorial to get a feeling of the Xcode's UI (optional)
+
+## What You'll Need
+
+**A Mac computer** - A Mac is required to install Xcode.
+
+---
+
+**An Apple account** - Required to download Xcode and install Xcode.
+
+---
+
+**Xcode** - Download and install Xcode from the App Store. After installation is complete, open it so that you go through the first-time setup, which can take up to 10 minutes. This will require around 6GB of hard drive space and up to 30 minutes total to complete.
+
+---
+
+<%= include('../_includes/_what-you-need') %>
+
+Start →
diff --git a/articles/identity-labs/04-single-page-app/exercise-01.md b/articles/identity-labs/04-single-page-app/exercise-01.md
new file mode 100644
index 0000000000..5318d93499
--- /dev/null
+++ b/articles/identity-labs/04-single-page-app/exercise-01.md
@@ -0,0 +1,366 @@
+---
+section: exercises
+description: Auth0 digital identity Lab 4, Exercise 1: Adding Sign On
+topics:
+ - digital identity
+ - OIDC
+ - OpenId Connect
+ - OAuth2
+contentType:
+ - index
+ - concept
+---
+# Lab 4, Exercise 1: Adding Sign On
+
+::: warning
+If you came to this page directly, go to the [first page of this lab](/identity-labs/04-single-page-app) and read through the instructions before getting started.
+:::
+
+In this lab, you will learn how to add sign-on capabilities to a Single-Page Application (SPA) and how to make this app consume an API that is secured with Auth0. You will integrate the SPA with Auth0 so that your users are able to use the Auth0 Universal Login Page to authenticate.
+
+The SPA in question is a vanilla JavaScript application that consumes an API similar to the one you have used in previous labs (this API also exposes a secured endpoint that returns a list of expenses). The difference is that the API in this lab does two additional things:
+
+- The API supports CORS to enable the SPA to consume it from a different domain (or a different port in a local environment).
+- The API exposes a public endpoint that returns a summary of its database. The SPA consumes this endpoint on its homepage to share the summary publicly.
+
+In this exercise, you will focus on integrating the SPA with Auth0 and getting the profile of the logged-in user. Exercise 2 will show how to consume the private endpoint exposed by the API.
+
+
+
+1. First, you will run a version of the app that is not integrated with Auth0. Open a new terminal and browse to `/lab-04/exercise-01/begin/api` in your locally-cloned copy of the [identity exercise repo](https://github.com/auth0/identity-102-exercises/). This is where the code for your API resides. Install the dependencies using npm.
+
+```bash
+# Make sure we're in the right directory
+❯ pwd
+/Users/username/identity-102-exercises/lab-04/exercise-01/begin/api
+
+❯ npm install
+# Ignore any warnings
+
+added XX packages in X.XXs
+```
+
+2. Make a copy of the `.env-sample` file and name it `.env`.
+
+```bash
+❯ cp .env-sample .env
+```
+
+3. Edit the new `.env` file to add your tenant domain and save the file.
+
+```text
+PORT=3001
+ISSUER_BASE_URL=https://${account.namespace}
+ALLOWED_AUDIENCES=https://expenses-api
+```
+
+4. Run the API:
+
+```bash
+❯ npm start
+```
+
+5. Open a new terminal in the `/lab-04/exercise-01/begin/spa` folder and run `http-server` to host the SPA.
+
+```bash
+# Navigating from the previous directory
+❯ cd ../spa
+
+# Make sure we're in the right directory
+❯ pwd
+/Users/username/identity-102-exercises/lab-04/exercise-01/begin/spa
+
+❯ npx http-server . -p 5000 -c-1
+npx: installed 26 in 3.459s
+Starting up http-server, serving .
+Available on:
+ http://127.0.0.1:5000
+ http://10.10.10.10:5000
+ http://192.168.1.4:5000
+Hit CTRL-C to stop the server
+```
+
+::: note
+On the command above, `-p 5000` makes the server listen on port 5000, and `-c-1` makes browsers ignore their own cache. This last parameter is important to facilitate the development process.
+:::
+
+6. Open [localhost:5000](http://localhost:5000) in a web browser, and you should see the page below. If you do not see the App Summary section, make sure your API is properly running at port 3001.
+
+
+
+This is the homepage of your SPA. Right now, this SPA has no integration with Auth0. Also, the app is only consuming the public endpoint provided by the API. This endpoint returns two pieces of information: the total number of expenses recorded in the database (two, in this case), and the sum of their amount ($144.00). The SPA is using this information to feed the "App Summary" section of the page you are seeing.
+
+7. To register this SPA with Auth0, log into the Auth0 Dashboard, go to the [Applications page](${manage_url}/#/applications), and click the **Create Application** button.
+
+8. Set a descriptive name (e.g., "Identity Lab 4 - Single Page App"), choose **Single Page Web Application** for the type, and click **Create**.
+
+9. You should now see the Quickstart section that describes how to integrate Auth0 with a production application. Click the **Settings** tab at the top to see the Application settings.
+
+10. Add `http://localhost:5000/#callback` to the **Allowed Callback URLs** field. Auth0 will allow redirects **only** to the URLs in this field after authentication. If the one provided in the authorization URL does not match any in this field, an error page will be displayed.
+
+11. Add `http://localhost:5000` to the **Allowed Web Origins** field. This field defines what URLs will be able to issue HTTP requests to Auth0 during a [silent authentication process](https://auth0.com/docs/api-auth/tutorials/silent-authentication). Your SPA will leverage this mechanism to check whether the current browser has an active session on the Auth0 authorization server.
+
+12. Add `http://localhost:5000` to the **Allowed Logout URLs** field. Auth0 will allow redirects **only** to the URLs in this field after logging out of the authorization server.
+
+13. Scroll down and click **Show Advanced Settings**, then **OAuth**. Make sure **JsonWebToken Signature Algorithm** is set to `RS256`.
+
+14. Scroll down and click **Save Changes**
+
+Now that you have registered your SPA with Auth0, you can update your code to integrate both. Below is a summary of the steps you will execute:
+
+- Import [auth0-spa-js](https://github.com/auth0/auth0-spa-js) and configure it with your own Auth0 settings.
+- Add code to handle the authentication callback.
+- Add code to restrict content to authenticated users only.
+- Implement login and logout.
+- Obtain and display user profile information.
+
+The [auth0-spa-js](https://github.com/auth0/auth0-spa-js) SDK is a simple, lightweight, and opinionated client developed by Auth0 that executes the OAuth 2.0 Authorization Code Grant Flow with PKCE. This client allows developers to quickly and securely implement authentication in their browser-based applications.
+
+15. Open the `spa/index.html` file and search for the `
+
+
+
+