├── .gitignore ├── LICENSE ├── README.md ├── TODO.md ├── access-policy ├── create-access-policy.sh ├── list-access-policy.sh └── readme.md ├── account-linking ├── .env.sample ├── link-idtoken.sh ├── link.sh └── unlink.sh ├── actions ├── create-action.sh ├── delete-action.sh ├── deploy-action.sh ├── empty-actions │ ├── custom-email-provider.js │ ├── custom-phone-provider.js │ └── post-login.js ├── empty-trigger-bindings.sh ├── get-action.sh ├── list-actions.sh ├── list-trigger-bindings.sh └── list-triggers.sh ├── anomaly ├── create-sheild.sh ├── delete-sheild.sh ├── list-sheilds.sh └── list-triggers.sh ├── asp ├── client-assertion.sh ├── create-asp.sh ├── delete-asp.sh ├── list-asp.sh └── readme.md ├── attack-protection ├── examples │ ├── breached-pw-detection.json │ ├── brute-force-protection.json │ └── suspicious-ip-throttling.json ├── get-breached-pw.sh ├── get-brute-force.sh ├── get-suspicous-ip.sh ├── update-breached-pw.sh ├── update-brute-force.sh └── update-suspicious-ip.sh ├── authorization ├── list-roles.sh └── readme.md ├── azure └── graph-member-groups.sh ├── branding ├── delete-page-template.sh ├── get-branding.sh ├── get-page-template.sh ├── put-page-template.sh ├── templates │ ├── base.html │ ├── custom-per-app.html │ ├── custom-per-org.html │ └── passkey-per-app.html └── update-branding.sh ├── ca ├── self-sign.sh ├── thumbprint.sh └── wildcard-cert.sh ├── clients ├── client-assertion.sh ├── client-public-profile.sh ├── create-client-credential.sh ├── create-client-grants.sh ├── create-client.sh ├── delete-client-credentials.sh ├── delete-client-grant.sh ├── delete-client.sh ├── list-client-credentials.sh ├── list-client-grants.sh ├── list-clients.sh ├── logout_token-sample.json ├── mark-1st-party-clients.sh ├── mark-3rd-party-clients.sh ├── register-client.sh ├── set-backchannel-logout-urls.sh ├── set-client-credential.sh ├── set-jar-credential.sh ├── set-session-transfer.sh ├── set-token-binding.sh ├── update-client-grants.sh ├── update-client-metadata.sh ├── update-client-quota.sh └── update-client-secret.sh ├── co ├── cross-origin.sh ├── silent.sh └── ul-classic.sh ├── connections ├── create-connection.sh ├── delete-connection-user.sh ├── delete-connection.sh ├── enable-context-realm.sh ├── list-connections.sh ├── mark-domain-level.sh ├── set-upstream-param.sh ├── templates │ ├── .gitignore │ ├── auth0-to-auth0.json │ ├── custom-social.json │ ├── fetchUserProfile-classic.js │ ├── msv2-common.json │ └── readme.md ├── update-connection-script.sh └── update-connection.sh ├── consent ├── consent.sh └── introspect.sh ├── cookie └── decode.sh ├── custom-domains ├── create-custom-domain.sh ├── list-custom-domains.sh └── update-custom-domain.sh ├── delegation ├── .env.sample └── 01-delegate.sh ├── devices ├── list-devices.sh └── revoke-device.sh ├── diagrams ├── co-silent.png ├── co-silent.webseq ├── otp-co.png └── otp-co.webseq ├── email-template └── get-template.sh ├── event-streams ├── create-event-stream.sh ├── enable-event-stream.sh ├── list-event-streams.sh └── webhook-cf-worker │ ├── worker.mjs │ └── wrangler.toml ├── extensions └── list.sh ├── grants ├── delete-grant.sh └── list-grants.sh ├── hlp └── preview.sh ├── jobs ├── build-dummy-users.sh ├── download-export.sh ├── generate-csv.sh ├── job-stats.sh ├── mk-import-job.sh ├── pbkdf2-samples.md ├── pbkdf2.sh ├── users-export.sh └── users-import.sh ├── liquid ├── context.json ├── package.json ├── render.sh └── sms.liquid ├── logs ├── export-csv.sh └── search.sh ├── mtls.md ├── multifactor ├── .env.sample ├── 01-start-flow.sh ├── 02-mfa-challenge.sh ├── 02-start-associate.sh ├── 03-complete-challenge.sh ├── authentication-method │ ├── create-authentication-method.sh │ ├── delete-authentication-method.sh │ ├── dump-cbor-base64.sh │ ├── ec-to-cbor.sh │ └── list-authentication-methods.sh ├── create-guardian-enrollment-ticket.sh ├── delete-enrollment.sh ├── delete-guardian-enrollment.sh ├── guardian │ ├── .gitignore │ ├── apns │ │ └── readme.md │ ├── create-jwk.sh │ ├── guardian-enroll.sh │ └── guardian-scan-qr.sh ├── list-authenticators.sh ├── list-enrolled-authenticators.sh ├── list-enrollments.sh ├── list-factors.sh ├── list-self-authenticators.sh ├── readme.md ├── remove-self-authenticators.sh ├── reset-mfa.sh ├── set-factor.sh ├── set-guardian-factor.sh └── totp.sh ├── nss ├── .gitignore └── mk-passwd.sh ├── organizations ├── invite.sh ├── list-organizations.sh └── update-organization-quota.sh ├── password-reset ├── .env.sample ├── change-password.sh └── token.sh ├── passwordless ├── .env.sample ├── otp-co.sh ├── otp-verify-legacy.sh ├── otp-verify.html ├── otp-verify.sh ├── passwordless-start.sh └── passwordless-verify.sh ├── prompt ├── get-partials.sh ├── get-render-settings.sh ├── set-partials.sh └── update-prompt.sh ├── resource-server ├── add-verification-key.sh ├── create-rs.sh ├── delete-rs.sh ├── list-rs.sh └── update-rs.sh ├── roles ├── create-role.sh ├── list-role-users.sh └── list-roles.sh ├── rules ├── create-rule.sh ├── delete-rule.sh ├── empty-rules │ ├── login_failure.js │ └── login_success.js └── list-rules.sh ├── saml ├── .gitignore ├── format-x509.sh ├── idp-change-signing-key-action.js ├── idp-download-cert.sh ├── idp-download-metadata.sh ├── idp-update-signing-keys.sh ├── keycloak-idp-init.sh ├── replay.php ├── saml-authnreq.sh ├── saml-replay-redirect-request-static.html ├── saml-replay-request-worker.js ├── saml-replay-response-worker.js ├── sp-disable-destination-check.sh ├── sp-disable-expiration-check.sh ├── sp-disable-inresponseto-check.sh ├── sp-disable-receipient-check.sh ├── sp-disable-responseid-check.sh ├── sp-download-cert.sh ├── sp-download-metadata.sh ├── sp-idp-post-sample.html ├── sp-set-destination-url.sh ├── sp-set-recipient-url.sh ├── sp-set-sign-request.sh ├── sp-update-entityId.sh └── sp-update-signing-cert.sh ├── sca.md ├── scim └── scim-get-user.sh ├── session ├── delete-refresh-token.sh ├── delete-session.sh ├── delete-user-refresh-tokens.sh ├── delete-user-sessions.sh ├── get-refresh-token.sh ├── get-session.sh ├── list-user-refresh-tokens.sh ├── list-user-sessions.sh └── revoke-web-session.sh ├── ss-sso ├── create-sso-ticket.sh └── list-ss-profiles.sh ├── tenant ├── cname-check.sh ├── create-tenant.sh ├── debug.sh ├── enable-sub-claim-mapping.sh ├── get-tenant-settings.sh ├── invite-admin.sh ├── list-admins.sh ├── readme.md ├── set-tenant-flag.sh └── signing-key.sh ├── token-exchange.md ├── token ├── introspect.sh └── revoke-rt.sh ├── tools ├── gh-clone-all.sh ├── mk-id_token.sh ├── single-line.sh ├── url-encode.sh └── xml-unescape.sh ├── twilio ├── .env-sample └── send-sms.sh ├── user-blocks ├── list-blocks.sh └── unblock.sh ├── users ├── .gitignore ├── block-user.sh ├── create-user.sh ├── custom-blocks │ ├── create-custom-block.sh │ ├── cub-demo.html │ ├── delete-custom-block.sh │ └── list-custom-blocks.sh ├── delete-user.sh ├── export-all-users.sh ├── get-user.sh ├── impersonate.sh ├── read-federated-tokenset.sh ├── scan-invalid-link.sh ├── search-user.sh ├── signup.sh ├── update-user-metadata.sh └── update-user.sh └── webtask └── setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *.pem 4 | jobs/*.json 5 | .env* 6 | .wrangler/ 7 | node_modules 8 | cookie.txt 9 | .idea 10 | yarn.lock 11 | package-lock.json 12 | qr.png 13 | *.json 14 | *.csv 15 | *.p12 16 | *.xml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2015-current Auth0, Inc. (http://auth0.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Auth0 Bash Samples 2 | 3 | Handy Bash scripts for Auth0 4 | 5 | ## What is Auth0? 6 | 7 | Auth0 helps you to: 8 | 9 | - Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, amont others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. 10 | - Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. 11 | - Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. 12 | - Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. 13 | - Analytics of how, when and where users are logging in. 14 | - Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). 15 | 16 | ## Create a free account in Auth0 17 | 18 | 1. Go to [Auth0](https://auth0.com) and click Sign Up. 19 | 2. Use Google, GitHub or Microsoft Account to login. 20 | 21 | ## Issue Reporting 22 | 23 | If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. 24 | 25 | ## Author 26 | 27 | Amin Abbaspour 28 | 29 | ## License 30 | 31 | This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info. 32 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Todo 2 | 3 | - [ ] remove `urlencode` method in favor of curl's --data-urlencode 4 | - [ ] add more SAML stuff 5 | - [ ] add README and sequence diagrams (esp CO) 6 | - [ ] test against other distros: Linux, BSD Family, SunOS family 7 | - [ ] offline_access with token and PKCE 8 | - [ ] export users 9 | - [ ] push notification sample 10 | - [ ] ./jwt/verify-rs256.sh 11 | - [ ] ticket API 12 | -------------------------------------------------------------------------------- /access-policy/list-access-policy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-i id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -A token # access_token. default from environment variable 19 | -i policy_id # access policy id 20 | -a audience # resource server API audience 21 | -s scopes # scopes to grant 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 -i id 27 | END 28 | exit $1 29 | } 30 | 31 | declare uri='' 32 | 33 | while getopts "e:A:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | A) access_token=${OPTARG} ;; 37 | i) uri="/${OPTARG}" ;; 38 | v) set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 47 | 48 | curl -k -s --request GET \ 49 | -H "Authorization: Bearer ${access_token}" \ 50 | --url "${AUTH0_DOMAIN_URL}api/v2/access-policies${uri}" | jq . 51 | -------------------------------------------------------------------------------- /access-policy/readme.md: -------------------------------------------------------------------------------- 1 | Access Policy Steps 2 | =================== 3 | 4 | A. M2M Client 5 | ------------- 6 | 1. build m2m 7 | ```bash 8 | cd ../clients 9 | ./create-client.sh -n "M2M for Grant Type" -t non_interactive 10 | ``` 11 | 12 | 2. grant client_credentials from prev step against management API with below scopes 13 | ```bash 14 | ./create-client-grants.sh -i H3l69Wu0pH81VQhk3kJjyXXXXXXX6h -m \ 15 | -s create:access_policies,read:access_policies,delete:access_policies,update:access_policies 16 | ``` 17 | 18 | 3. Figure out what's client_secret of this new client 19 | ```bash 20 | ./list-clients.sh 21 | ``` 22 | 23 | B. Register 24 | ----------- 25 | 1. Use M2M client to get a management API access_token 26 | 27 | ```bash 28 | cd ../login 29 | export access_token=$(./client-credentials.sh -t tenant@region \ 30 | -c bMZEeDKSzQkoDpJiKgZuhTHgRzZ4VFRE -x XXXX -m | jq -r .access_token) 31 | ``` 32 | 33 | 2. register API Grant against a user with your API 34 | ```bash 35 | cd ../api-policy 36 | ./create-api-policy.sh -c rs.client.id -a newapi -s do:something 37 | ``` 38 | -------------------------------------------------------------------------------- /account-linking/.env.sample: -------------------------------------------------------------------------------- 1 | AUTH0_DOMAIN=tenant.region.auth0.com 2 | AUTH0_CLIENT_ID=XXXXXXX 3 | -------------------------------------------------------------------------------- /account-linking/link-idtoken.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-p user_id] [-s id_token] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # APIv2 access token with $(update:current_user_identities) scope 19 | -p user_id # primary user_id (i.e. current identities) 20 | -s id_token # secondary user id_token 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 -a 'eyJhbGci...' -p 'auth0|xxxx' -s 'eyJhbGc...' 26 | END 27 | exit $1 28 | } 29 | 30 | declare access_token='' 31 | declare user_id='' 32 | declare id_token='' 33 | declare opt_verbose=0 34 | 35 | while getopts "e:a:p:s:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | a) access_token=${OPTARG} ;; 39 | p) user_id=${OPTARG} ;; 40 | s) id_token=${OPTARG} ;; 41 | v) opt_verbose=1 ;; #set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 48 | 49 | [[ -z "${user_id}" ]] && { echo >&2 "ERROR: user_id undefined"; usage 1; } 50 | 51 | [[ -z "${id_token}" ]] && { echo >&2 "ERROR: id_token undefined"; usage 1; } 52 | 53 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 54 | 55 | declare -r BODY=$(cat </dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i action_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i id # action_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i ec17f56f-e9d8-4971-999e-a518c90e7987 25 | END 26 | exit $1 27 | } 28 | 29 | declare id='' 30 | 31 | while getopts "e:a:i:hv?" opt; do 32 | case ${opt} in 33 | e) source ${OPTARG} ;; 34 | a) access_token=${OPTARG} ;; 35 | i) id=${OPTARG} ;; 36 | v) set -x;; 37 | h | ?) usage 0 ;; 38 | *) usage 1 ;; 39 | esac 40 | done 41 | 42 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 43 | 44 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 45 | declare -r EXPECTED_SCOPE="delete:actions" 46 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 47 | 48 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 49 | 50 | [[ -z "${id}" ]] && { echo >&2 "ERROR: action id undefined."; usage 1; } 51 | 52 | curl -s -X DELETE -H "Authorization: Bearer ${access_token}" \ 53 | --url ${AUTH0_DOMAIN_URL}api/v2/actions/actions/${id} | jq . 54 | -------------------------------------------------------------------------------- /actions/deploy-action.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i action_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i id # action_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i ec17f56f-e9d8-4971-999e-a518c90e7987 25 | END 26 | exit $1 27 | } 28 | 29 | declare id='' 30 | 31 | while getopts "e:a:i:hv?" opt; do 32 | case ${opt} in 33 | e) source ${OPTARG} ;; 34 | a) access_token=${OPTARG} ;; 35 | i) id=${OPTARG} ;; 36 | v) set -x;; 37 | h | ?) usage 0 ;; 38 | *) usage 1 ;; 39 | esac 40 | done 41 | 42 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 43 | 44 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 45 | declare -r EXPECTED_SCOPE="create:actions" 46 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 47 | 48 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 49 | 50 | [[ -z "${id}" ]] && { echo >&2 "ERROR: action id undefined."; usage 1; } 51 | 52 | curl -s -X POST -H "Authorization: Bearer ${access_token}" \ 53 | --url ${AUTH0_DOMAIN_URL}api/v2/actions/actions/${id}/deploy | jq . 54 | -------------------------------------------------------------------------------- /actions/empty-actions/custom-email-provider.js: -------------------------------------------------------------------------------- 1 | exports.onExecuteCustomEmailProvider = async (event, api) => {}; 2 | -------------------------------------------------------------------------------- /actions/empty-actions/custom-phone-provider.js: -------------------------------------------------------------------------------- 1 | exports.onExecuteCustomPhoneProvider = async (event, api) => {}; 2 | -------------------------------------------------------------------------------- /actions/empty-actions/post-login.js: -------------------------------------------------------------------------------- 1 | exports.onExecutePostLogin = async (event, api) => { 2 | console.log('User logging in: ' + event.user.email); 3 | }; -------------------------------------------------------------------------------- /actions/empty-trigger-bindings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2025-02-20 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-t trigger_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -t trigger_id # trigger id. eg: post-login, pre-user-registration 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 25 | $0 26 | END 27 | exit $1 28 | } 29 | 30 | declare trigger_id='' 31 | 32 | while getopts "e:a:t:hv?" opt; do 33 | case ${opt} in 34 | e) source ${OPTARG} ;; 35 | a) access_token=${OPTARG} ;; 36 | t) trigger_id=${OPTARG} ;; 37 | v) set -x;; 38 | h | ?) usage 0 ;; 39 | *) usage 1 ;; 40 | esac 41 | done 42 | 43 | [[ -z "${trigger_id}" ]] && { echo >&2 "ERROR: trigger_id undefined."; usage 1; } 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 47 | declare -r EXPECTED_SCOPE="update:actions" 48 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 49 | 50 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 51 | 52 | declare BODY='{"bindings":[]}' 53 | 54 | curl -s -X PATCH -H "Authorization: Bearer ${access_token}" \ 55 | -H 'Content-Type: application/json' \ 56 | --url "${AUTH0_DOMAIN_URL}api/v2/actions/triggers/${trigger_id}/bindings" \ 57 | -d "${BODY}" 58 | -------------------------------------------------------------------------------- /actions/get-action.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i action_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i id # action_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i ec17f56f-e9d8-4971-999e-a518c90e7987 25 | END 26 | exit $1 27 | } 28 | 29 | declare id='' 30 | 31 | while getopts "e:a:i:hv?" opt; do 32 | case ${opt} in 33 | e) source ${OPTARG} ;; 34 | a) access_token=${OPTARG} ;; 35 | i) id=${OPTARG} ;; 36 | v) set -x;; 37 | h | ?) usage 0 ;; 38 | *) usage 1 ;; 39 | esac 40 | done 41 | 42 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 43 | 44 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 45 | declare -r EXPECTED_SCOPE="read:actions" 46 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 47 | 48 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 49 | 50 | [[ -z "${id}" ]] && { echo >&2 "ERROR: action id undefined."; usage 1; } 51 | 52 | curl -s -H "Authorization: Bearer ${access_token}" \ 53 | --url ${AUTH0_DOMAIN_URL}api/v2/actions/actions/${id} | jq . 54 | -------------------------------------------------------------------------------- /actions/list-trigger-bindings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-t trigger_id] [-n name] [-d (true|false)] [-i (true|false)] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -t trigger_id # trigger id. eg: post-login, pre-user-registration 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 25 | $0 26 | END 27 | exit $1 28 | } 29 | 30 | declare trigger_id='' 31 | 32 | while getopts "e:a:t:hv?" opt; do 33 | case ${opt} in 34 | e) source ${OPTARG} ;; 35 | a) access_token=${OPTARG} ;; 36 | t) trigger_id=${OPTARG} ;; 37 | v) set -x;; 38 | h | ?) usage 0 ;; 39 | *) usage 1 ;; 40 | esac 41 | done 42 | 43 | [[ -z "${trigger_id}" ]] && { echo >&2 "ERROR: trigger_id undefined."; usage 1; } 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 47 | declare -r EXPECTED_SCOPE="read:actions" 48 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 49 | 50 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 51 | 52 | curl -s --get -H "Authorization: Bearer ${access_token}" \ 53 | --url "${AUTH0_DOMAIN_URL}api/v2/actions/triggers/${trigger_id}/bindings" | jq . 54 | -------------------------------------------------------------------------------- /actions/list-triggers.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-T trigger_id] [-n name] [-d (true|false)] [-i (true|false)] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 24 | $0 25 | END 26 | exit $1 27 | } 28 | 29 | while getopts "e:a:hv?" opt; do 30 | case ${opt} in 31 | e) source ${OPTARG} ;; 32 | a) access_token=${OPTARG} ;; 33 | v) set -x;; 34 | h | ?) usage 0 ;; 35 | *) usage 1 ;; 36 | esac 37 | done 38 | 39 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 40 | 41 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 42 | declare -r EXPECTED_SCOPE="read:actions" 43 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 44 | 45 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 46 | 47 | curl -s --get -H "Authorization: Bearer ${access_token}" \ 48 | --url ${AUTH0_DOMAIN_URL}api/v2/actions/triggers | jq . 49 | -------------------------------------------------------------------------------- /anomaly/delete-sheild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i id # shield_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i shi_nXhRD52npETMXweg 25 | END 26 | exit $1 27 | } 28 | 29 | declare shield_id='' 30 | 31 | while getopts "e:a:i:hv?" opt; do 32 | case ${opt} in 33 | e) source ${OPTARG} ;; 34 | a) access_token=${OPTARG} ;; 35 | i) shield_id=${OPTARG} ;; 36 | v) opt_verbose=1 ;; #set -x;; 37 | h | ?) usage 0 ;; 38 | *) usage 1 ;; 39 | esac 40 | done 41 | 42 | [[ -z ${shield_id} ]] && { echo >&2 "ERROR: no 'shield_id' defined" 43 | exit 1 44 | } 45 | 46 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 47 | exit 1 48 | } 49 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 50 | 51 | curl -s -X DELETE -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 52 | "${AUTH0_DOMAIN_URL}api/v2/anomaly/shields/${shield_id}" 53 | -------------------------------------------------------------------------------- /anomaly/list-sheilds.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 24 | END 25 | exit $1 26 | } 27 | 28 | while getopts "e:a:i:hv?" opt; do 29 | case ${opt} in 30 | e) source ${OPTARG} ;; 31 | a) access_token=${OPTARG} ;; 32 | v) opt_verbose=1 ;; #set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 39 | exit 1 40 | } 41 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 42 | 43 | curl -s --get -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 44 | "${AUTH0_DOMAIN_URL}api/v2/anomaly/shields" 45 | -------------------------------------------------------------------------------- /anomaly/list-triggers.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 24 | END 25 | exit $1 26 | } 27 | 28 | while getopts "e:a:hv?" opt; do 29 | case ${opt} in 30 | e) source ${OPTARG} ;; 31 | a) access_token=${OPTARG} ;; 32 | v) opt_verbose=1 ;; #set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 39 | exit 1 40 | } 41 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 42 | 43 | curl -s --get -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 44 | "${AUTH0_DOMAIN_URL}api/v2/anomaly/triggers" 45 | -------------------------------------------------------------------------------- /asp/list-asp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | declare user_id='' 17 | 18 | function usage() { 19 | cat <&2 20 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 21 | -e file # .env file location (default cwd) 22 | -a token # access_token. default from environment variable 23 | -i user_id # user_id, e.g. 'auth0|5b5fb9702e0e740478884234' 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 -i 'auth0|5b5fb9702e0e740478884234' 29 | END 30 | exit $1 31 | } 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) user_id=${OPTARG} ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | 47 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 48 | declare -r EXPECTED_SCOPE="read:user_application_passwords" 49 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 50 | 51 | [[ -z "${user_id}" ]] && { echo >&2 "ERROR: user_id undefined."; usage 1; } 52 | 53 | 54 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 55 | 56 | curl -s -H "Authorization: Bearer ${access_token}" \ 57 | --request GET \ 58 | --url "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}/application-passwords" 59 | -------------------------------------------------------------------------------- /asp/readme.md: -------------------------------------------------------------------------------- 1 | ASP Steps 2 | ========= 3 | 4 | A. API 5 | ------ 6 | 1. build a set of private/public keys 7 | ```bash 8 | cd ../ca 9 | ./self-sign.sh -n backend-api 10 | ``` 11 | 12 | 2. create resource-server with arbitrary API 13 | ```bash 14 | cd ../resource-server/ 15 | ./create-rs.sh -i https://backend.api -n "Backend API" -s read:data,write:data 16 | ``` 17 | 18 | 3. register public key against verificationKey of your resource server 19 | ```bash 20 | ./add-verification-key.sh -i 5c20475819a2bc74962784c6 -k backend-api -f ../ca/backend-api-public.pem 21 | ``` 22 | 23 | B. M2M Client 24 | ------------- 25 | 1. build m2m 26 | ```bash 27 | cd ../clients 28 | ./create-client.sh -n "M2M for ASP" -t non_interactive 29 | ``` 30 | 31 | 2. grant client_credentials from prev step against management API with below scopes 32 | ```bash 33 | ./create-client-grants.sh -i bMZEeDKSzQkoDpJiKgZuhTHgRzZ4VFRE -m \ 34 | -s create:user_application_passwords,read:user_application_passwords,delete:user_application_passwords 35 | ``` 36 | 37 | 3. Figure out what's client_secret of this new client 38 | ```bash 39 | ./list-clients.sh 40 | ``` 41 | 42 | C. Register 43 | ----------- 44 | 1. Use M2M client to get a management API access_token 45 | 46 | ```bash 47 | cd ../login 48 | export access_token=$(./client-credentials.sh -t tenant@region \ 49 | -c bMZEeDKSzQkoDpJiKgZuhTHgRzZ4VFRE -x XXXX -m | jq -r .access_token) 50 | ``` 51 | 52 | 2. register ASP against a user with your API 53 | ```bash 54 | cd ../asp 55 | ./create-asp.sh -i 'auth0|5b5fb9702e0e740478884234' \ 56 | -a https://backend.api -n "My ASP for Backend API" \ 57 | -s read:data,write:data 58 | ``` 59 | 60 | Record `value`. It's user's ASP against your API. 61 | 62 | D. Validate 63 | ----------- 64 | 1. create a client-assertion jwt using private key in step A-1 and with `sub` equal to API identifier in step A-2 & `aud` to auth0 tenant 65 | 66 | ```bash 67 | cd ../asp 68 | ./client-assertion.sh -t tenant@region -a https://backend.api \ 69 | -k backend-api -f ../ca/backend-api-private.pem 70 | ``` 71 | 72 | 2. Introspect ASP 73 | ```bash 74 | cd ../token 75 | ./introspect.sh -t tenant@region -a 'ASP-from-C-2' -c clients 76 | ``` 77 | 78 | -------------------------------------------------------------------------------- /attack-protection/examples/breached-pw-detection.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled": true, 3 | "shields": [ 4 | "admin_notification", 5 | "user_notification", 6 | "block" 7 | ], 8 | "admin_notification_frequency": [ 9 | "immediately" 10 | ], 11 | "method": "standard" 12 | } -------------------------------------------------------------------------------- /attack-protection/examples/brute-force-protection.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled": true, 3 | "shields": [ 4 | "user_notification", 5 | "block" 6 | ], 7 | "mode": "count_per_identifier_and_ip", 8 | "allowlist": [ 9 | "1.1.1.1" 10 | ], 11 | "max_attempts": 10 12 | } -------------------------------------------------------------------------------- /attack-protection/examples/suspicious-ip-throttling.json: -------------------------------------------------------------------------------- 1 | { 2 | "enabled": true, 3 | "shields": [ 4 | "admin_notification", 5 | "block" 6 | ], 7 | "allowlist": [], 8 | "stage": { 9 | "pre-login": { 10 | "max_attempts": 100, 11 | "rate": 864000 12 | }, 13 | "pre-user-registration": { 14 | "max_attempts": 50, 15 | "rate": 1200 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /attack-protection/get-breached-pw.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 24 | END 25 | exit $1 26 | } 27 | 28 | while getopts "e:a:hv?" opt; do 29 | case ${opt} in 30 | e) source ${OPTARG} ;; 31 | a) access_token=${OPTARG} ;; 32 | v) set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 39 | 40 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 41 | declare -r EXPECTED_SCOPE="read:attack_protection" 42 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 43 | 44 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 45 | 46 | curl -s -H "Authorization: Bearer ${access_token}" \ 47 | --url ${AUTH0_DOMAIN_URL}api/v2/attack-protection/breached-password-detection | jq . 48 | -------------------------------------------------------------------------------- /attack-protection/get-brute-force.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 24 | END 25 | exit $1 26 | } 27 | 28 | while getopts "e:a:hv?" opt; do 29 | case ${opt} in 30 | e) source ${OPTARG} ;; 31 | a) access_token=${OPTARG} ;; 32 | v) set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 39 | 40 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 41 | declare -r EXPECTED_SCOPE="read:attack_protection" 42 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 43 | 44 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 45 | 46 | curl -s -H "Authorization: Bearer ${access_token}" \ 47 | --url ${AUTH0_DOMAIN_URL}api/v2/attack-protection/brute-force-protection | jq . 48 | -------------------------------------------------------------------------------- /attack-protection/get-suspicous-ip.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 24 | END 25 | exit $1 26 | } 27 | 28 | while getopts "e:a:hv?" opt; do 29 | case ${opt} in 30 | e) source ${OPTARG} ;; 31 | a) access_token=${OPTARG} ;; 32 | v) set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 39 | 40 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 41 | declare -r EXPECTED_SCOPE="read:attack_protection" 42 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 43 | 44 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 45 | 46 | curl -s -H "Authorization: Bearer ${access_token}" \ 47 | --url ${AUTH0_DOMAIN_URL}api/v2/attack-protection/suspicious-ip-throttling | jq . 48 | -------------------------------------------------------------------------------- /authorization/list-roles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 26 | END 27 | exit $1 28 | } 29 | 30 | while getopts "e:a:hv?" opt; do 31 | case ${opt} in 32 | e) source ${OPTARG} ;; 33 | a) access_token=${OPTARG} ;; 34 | v) opt_verbose=1 ;; #set -x;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 41 | 42 | 43 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 44 | declare -r EXPECTED_SCOPE="read:roles" 45 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 46 | 47 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 48 | 49 | curl -s -H "Authorization: Bearer ${access_token}" \ 50 | --url ${AUTH0_DOMAIN_URL}api/v2/roles | jq '.' 51 | -------------------------------------------------------------------------------- /authorization/readme.md: -------------------------------------------------------------------------------- 1 | B. M2M Client 2 | ------------- 3 | 1. build m2m 4 | ```bash 5 | cd ../clients 6 | ./create-client.sh -n "M2M for Authorization" -t non_interactive 7 | ``` 8 | 9 | 2. grant client_credentials from prev step against management API with below scopes 10 | ```bash 11 | ./create-client-grants.sh -i IIIIIIII -m \ 12 | -s create:roles,delete:roles,read:roles,update:roles 13 | ``` 14 | 15 | 3. Figure out what's client_secret of this new client 16 | ```bash 17 | ./list-clients.sh | grep -A2 IIIIII 18 | ``` 19 | 20 | 21 | 4. Use M2M client to get a management API access_token 22 | 23 | ```bash 24 | cd ../login 25 | export access_token=$(./client-credentials.sh -t tenant@region \ 26 | -c IIIII -x XXXX -m | jq -r .access_token) 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /azure/graph-member-groups.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | declare uid='USERNAME@ORG.onmicrosoft.com' 10 | 11 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: no onmicrosoft access_token present. export it." 12 | exit 1 13 | } 14 | 15 | curl 'https://graph.windows.net/myorganization/users/${uid}/getMemberGroups?api-version=1.6' \ 16 | -H 'Accept: application/json, text/plain, */*' \ 17 | -H 'Referer: https://graphexplorer.azurewebsites.net/' \ 18 | -H 'Origin: https://graphexplorer.azurewebsites.net' \ 19 | -H "Authorization: Bearer ${access_token}" \ 20 | -H 'Content-Type: application/json;charset=UTF-8' \ 21 | --data-binary $'{"securityEnabledOnly" : true}' 22 | -------------------------------------------------------------------------------- /branding/delete-page-template.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 16 | -e file # .env file location (default cwd) 17 | -a token # access_token. default from environment variable 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -f "enable_client_connections":true 23 | END 24 | exit ${1} 25 | } 26 | 27 | while getopts "e:a:hv?" opt; do 28 | case ${opt} in 29 | e) source "${OPTARG}" ;; 30 | a) access_token=${OPTARG} ;; 31 | v) opt_verbose=1 ;; #set -x;; 32 | h | ?) usage 0 ;; 33 | *) usage 1 ;; 34 | esac 35 | done 36 | 37 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 38 | 39 | 40 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 41 | declare -r EXPECTED_SCOPE="delete:branding" 42 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 43 | 44 | declare -r AUTH0_DOMAIN_URL=$(echo "${access_token}" | awk -F. '{print $2}' | base64 -di 2>/dev/null | jq -r '.iss') 45 | 46 | curl -s -X DELETE -H "Authorization: Bearer ${access_token}" \ 47 | --url "${AUTH0_DOMAIN_URL}api/v2/branding/templates/universal-login" 48 | -------------------------------------------------------------------------------- /branding/get-branding.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 16 | -e file # .env file location (default cwd) 17 | -a token # access_token. default from environment variable 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -f "enable_client_connections":true 23 | END 24 | exit ${1} 25 | } 26 | 27 | while getopts "e:a:hv?" opt; do 28 | case ${opt} in 29 | e) source "${OPTARG}" ;; 30 | a) access_token=${OPTARG} ;; 31 | v) opt_verbose=1 ;; #set -x;; 32 | h | ?) usage 0 ;; 33 | *) usage 1 ;; 34 | esac 35 | done 36 | 37 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 38 | 39 | 40 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 41 | declare -r EXPECTED_SCOPE="read:branding" 42 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 43 | 44 | declare -r AUTH0_DOMAIN_URL=$(echo "${access_token}" | awk -F. '{print $2}' | base64 -di 2>/dev/null | jq -r '.iss') 45 | 46 | curl -s -H "Authorization: Bearer ${access_token}" \ 47 | --url "${AUTH0_DOMAIN_URL}api/v2/branding" | jq '.' 48 | -------------------------------------------------------------------------------- /branding/get-page-template.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 16 | -e file # .env file location (default cwd) 17 | -a token # access_token. default from environment variable 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -f "enable_client_connections":true 23 | END 24 | exit ${1} 25 | } 26 | 27 | while getopts "e:a:hv?" opt; do 28 | case ${opt} in 29 | e) source "${OPTARG}" ;; 30 | a) access_token=${OPTARG} ;; 31 | v) opt_verbose=1 ;; #set -x;; 32 | h | ?) usage 0 ;; 33 | *) usage 1 ;; 34 | esac 35 | done 36 | 37 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 38 | 39 | 40 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 41 | declare -r EXPECTED_SCOPE="read:branding" 42 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 43 | 44 | declare -r AUTH0_DOMAIN_URL=$(echo "${access_token}" | awk -F. '{print $2}' | base64 -di 2>/dev/null | jq -r '.iss') 45 | 46 | curl -s -H "Authorization: Bearer ${access_token}" \ 47 | --url "${AUTH0_DOMAIN_URL}api/v2/branding/templates/universal-login" 48 | -------------------------------------------------------------------------------- /branding/put-page-template.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 16 | -e file # .env file location (default cwd) 17 | -a token # access_token. default from environment variable 18 | -f file # template file 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 -f "enable_client_connections":true 24 | END 25 | exit ${1} 26 | } 27 | 28 | declare template_file='' 29 | 30 | while getopts "e:a:f:hv?" opt; do 31 | case ${opt} in 32 | e) source "${OPTARG}" ;; 33 | a) access_token=${OPTARG} ;; 34 | f) template_file=${OPTARG} ;; 35 | v) opt_verbose=1 ;; #set -x;; 36 | h | ?) usage 0 ;; 37 | *) usage 1 ;; 38 | esac 39 | done 40 | 41 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 42 | 43 | 44 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 45 | declare -r EXPECTED_SCOPE="update:branding" 46 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 47 | 48 | [[ -z "${template_file}" ]] && { echo >&2 "ERROR: template_file undefined."; usage 1; } 49 | 50 | 51 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 52 | 53 | curl -X PUT -H "Authorization: Bearer ${access_token}" \ 54 | --url "${AUTH0_DOMAIN_URL}api/v2/branding/templates/universal-login" \ 55 | --data "@${template_file}" \ 56 | -H "Content-Type: text/html" 57 | -------------------------------------------------------------------------------- /branding/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Welcome to {{ application.name }} 5 | {%- auth0:head -%} 6 | 18 | 19 | 20 |
21 | {%- auth0:widget -%} 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /branding/templates/passkey-per-app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ prompt.screen.texts.pageTitle }} 5 | {%- auth0:head -%} 6 | {% if application.metadata.PASSKEY == "false" %} 7 | 12 | {% endif %} 13 | 14 | 15 |
16 | {%- auth0:widget -%} 17 |
18 | {% if application.metadata.PASSKEY == "false" %} 19 | 59 | {% endif %} 60 | 61 | 62 | -------------------------------------------------------------------------------- /ca/self-sign.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v openssl >/dev/null || { echo >&2 "error: openssl not found"; exit 3; } 12 | 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-n domain] 16 | -n name # name of key pair (default is localhost) 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -n backend-api 22 | END 23 | exit $1 24 | } 25 | 26 | declare pair_name='localhost' 27 | declare opt_verbose=0 28 | 29 | while getopts "n:hv?" opt; do 30 | case ${opt} in 31 | n) pair_name=${OPTARG} ;; 32 | v) opt_verbose=1 ;; #set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z "${pair_name}" ]] && { echo >&2 "ERROR: pair_name undefined."; usage 1; } 39 | 40 | 41 | declare -r private_key="${pair_name}-private.pem" 42 | declare -r cert_key="${pair_name}-cert.pem" 43 | declare -r public_key="${pair_name}-public.pem" 44 | 45 | cat >openssl.cnf <<-EOF 46 | [req] 47 | distinguished_name = req_distinguished_name 48 | x509_extensions = v3_req 49 | prompt = no 50 | default_bits = 2048 51 | [req_distinguished_name] 52 | CN = ${pair_name} 53 | [v3_req] 54 | keyUsage = keyEncipherment, dataEncipherment 55 | extendedKeyUsage = serverAuth 56 | EOF 57 | 58 | openssl req -nodes -new -x509 -config openssl.cnf -days 365 -keyout "${private_key}" -out "${cert_key}" 59 | openssl x509 -inform PEM -in ${cert_key} -pubkey -noout >"${public_key}" 60 | 61 | rm openssl.cnf 62 | -------------------------------------------------------------------------------- /ca/thumbprint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2023-10-25 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v openssl >/dev/null || { echo >&2 "error: openssl not found"; exit 3; } 12 | command -v xxd >/dev/null || { echo >&2 "error: xxd not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-n domain] 17 | -f cert # certificate file to generate CNF S256 value to match for token binding 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -f mycert.pem 23 | END 24 | exit $1 25 | } 26 | 27 | declare cert_file='' 28 | 29 | while getopts "f:hv?" opt; do 30 | case ${opt} in 31 | f) cert_file=${OPTARG} ;; 32 | v) set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z "${cert_file}" ]] && { echo >&2 "ERROR: cert_file undefined."; usage 1; } 39 | [[ ! -f "${cert_file}" ]] && { echo >&2 "ERROR: cert_file not found: ${cert_file}"; usage 1; } 40 | 41 | openssl x509 -in "${cert_file}" -outform DER | openssl dgst -sha256 | cut -d" " -f2 | xxd -r -p - | openssl enc -a | tr -d '=' -------------------------------------------------------------------------------- /ca/wildcard-cert.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v openssl >/dev/null || { echo >&2 "error: openssl not found"; exit 3; } 12 | 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-d domain] 16 | -d domain # domain 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -d mydomain.local 22 | END 23 | exit $1 24 | } 25 | 26 | declare DOMAIN='' 27 | declare opt_verbose=0 28 | 29 | while getopts "d:hv?" opt; do 30 | case ${opt} in 31 | d) DOMAIN=${OPTARG} ;; 32 | v) opt_verbose=1 ;; #set -x;; 33 | h | ?) usage 0 ;; 34 | *) usage 1 ;; 35 | esac 36 | done 37 | 38 | [[ -z "${DOMAIN}" ]] && { echo >&2 "ERROR: DOMAIN undefined."; usage 1; } 39 | 40 | declare -r private_key="${DOMAIN}-private.pem" 41 | declare -r public_key="${DOMAIN}-public.pem" 42 | 43 | echo " Generating wildcard certificate: *.$DOMAIN" 44 | 45 | cat >openssl.cnf <<-EOF 46 | [req] 47 | distinguished_name = req_distinguished_name 48 | x509_extensions = v3_req 49 | prompt = no 50 | [req_distinguished_name] 51 | CN = *.$DOMAIN 52 | [v3_req] 53 | keyUsage = keyEncipherment, dataEncipherment 54 | extendedKeyUsage = serverAuth 55 | EOF 56 | 57 | openssl req \ 58 | -new \ 59 | -newkey rsa:2048 \ 60 | -sha1 \ 61 | -days 3650 \ 62 | -nodes \ 63 | -x509 \ 64 | -keyout $DOMAIN.pkcs8.key \ 65 | -out $DOMAIN.crt \ 66 | -config openssl.cnf 67 | 68 | openssl rsa -in $DOMAIN.pkcs8.key -out $DOMAIN.key 69 | 70 | rm openssl.cnf $DOMAIN.pkcs8.key 71 | -------------------------------------------------------------------------------- /clients/client-public-profile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | 10 | set -eo pipefail 11 | 12 | function usage() { 13 | cat <&2 14 | USAGE: $0 [-e env] [-a access_token] [-n name] [-t type] [-i client_id] [-p PEM] [-c callbacks] [-v|-h] 15 | -e file # .env file location (default cwd) 16 | -t tenant # auth0 tenant 17 | -d domain # auth0 domain 18 | -i client_id # client_id (if accept_client_id_on_creation is on) 19 | -h|? # usage 20 | -v # verbose 21 | 22 | eg, 23 | $0 -d tenant -i client_123 24 | END 25 | exit $1 26 | } 27 | 28 | declare AUTH0_DOMAIN='' 29 | declare AUTH0_CLIENT_ID='' 30 | 31 | while getopts "e:t:d:i:hv?" opt; do 32 | case ${opt} in 33 | e) source ${OPTARG} ;; 34 | t) AUTH0_DOMAIN=$(echo "${OPTARG}.auth0.com" | tr '@' '.') ;; 35 | d) AUTH0_DOMAIN=${OPTARG} ;; 36 | i) AUTH0_CLIENT_ID=${OPTARG} ;; 37 | v) set -x;; 38 | h | ?) usage 0 ;; 39 | *) usage 1 ;; 40 | esac 41 | done 42 | 43 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined"; usage 1; } 44 | [[ -z "${AUTH0_CLIENT_ID}" ]] && { echo >&2 "ERROR: AUTH0_CLIENT_ID undefined"; usage 1; } 45 | 46 | curl -s "https://${AUTH0_DOMAIN}/client/${AUTH0_CLIENT_ID}.js" | sed -n 's/Auth0\.setClient(\(.*\));/\1/p' | jq . 47 | -------------------------------------------------------------------------------- /clients/delete-client-grant.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | 10 | set -eo pipefail 11 | 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 14 | 15 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 16 | 17 | function usage() { 18 | cat <&2 19 | USAGE: $0 [-e env] [-a access_token] [-i id] [-v|-h] 20 | -e file # .env file location (default cwd) 21 | -a token # access_token. default from environment variable 22 | -i id # client grant id 23 | -h|? # usage 24 | -v # verbose 25 | 26 | eg, 27 | $0 -i g123 28 | END 29 | exit $1 30 | } 31 | 32 | declare grant_id='' 33 | 34 | 35 | 36 | while getopts "e:a:i:n:s:hv?" opt; do 37 | case ${opt} in 38 | e) source ${OPTARG} ;; 39 | a) access_token=${OPTARG} ;; 40 | i) grant_id=${OPTARG} ;; 41 | v) opt_verbose=1 ;; #set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 48 | 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="delete:client_grants" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z "${grant_id}" ]] && { echo >&2 "ERROR: grant_id undefined."; usage 1; } 55 | 56 | 57 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 58 | 59 | curl -k --request DELETE \ 60 | -H "Authorization: Bearer ${access_token}" \ 61 | --url ${AUTH0_DOMAIN_URL}api/v2/client-grants/${grant_id} 62 | -------------------------------------------------------------------------------- /clients/delete-client.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | 10 | set -eo pipefail 11 | 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 14 | 15 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 16 | 17 | function usage() { 18 | cat <&2 19 | USAGE: $0 [-e env] [-a access_token] [-i id] [-v|-h] 20 | -e file # .env file location (default cwd) 21 | -a token # access_token. default from environment variable 22 | -i id # client id 23 | -h|? # usage 24 | -v # verbose 25 | 26 | eg, 27 | $0 -i c_123 28 | END 29 | exit $1 30 | } 31 | 32 | declare client_id='' 33 | 34 | 35 | 36 | while getopts "e:a:i:hv?" opt; do 37 | case ${opt} in 38 | e) source ${OPTARG} ;; 39 | a) access_token=${OPTARG} ;; 40 | i) client_id=${OPTARG} ;; 41 | v) opt_verbose=1 ;; #set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 48 | 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="delete:clients" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z "${client_id}" ]] && { echo >&2 "ERROR: client_id undefined." ; usage 1; } 55 | 56 | 57 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 58 | 59 | curl --request DELETE \ 60 | -H "Authorization: Bearer ${access_token}" \ 61 | --url "${AUTH0_DOMAIN_URL}api/v2/clients/${client_id}" 62 | -------------------------------------------------------------------------------- /clients/list-client-credentials.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-i client_id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -i client_id # client id 22 | -c cred_id # client credentials id 23 | -h|? # usage 24 | -v # verbose 25 | 26 | eg, 27 | $0 -c c123 28 | END 29 | exit $1 30 | } 31 | 32 | declare client_id='' 33 | declare query='' 34 | 35 | while getopts "e:a:i:c:hv?" opt; do 36 | case ${opt} in 37 | e) source ${OPTARG} ;; 38 | a) access_token=${OPTARG} ;; 39 | i) client_id="${OPTARG}" ;; 40 | c) query="/${OPTARG}" ;; 41 | v) opt_verbose=1 ;; #set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 48 | [[ -z "${client_id}" ]] && { echo >&2 "ERROR: client_id undefined."; usage 1; } 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="read:client_credentials" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 55 | 56 | curl -k -s -H "Authorization: Bearer ${access_token}" \ 57 | --url "${AUTH0_DOMAIN_URL}api/v2/clients/${client_id}/credentials${query}" | jq '.' 58 | -------------------------------------------------------------------------------- /clients/list-client-grants.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | # todo: client_id query parameter 17 | 18 | function usage() { 19 | cat <&2 20 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 21 | -e file # .env file location (default cwd) 22 | -a token # access_token. default from environment variable 23 | -i id # client_id 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 29 | END 30 | exit $1 31 | } 32 | 33 | declare query='' 34 | 35 | while getopts "e:a:i:hv?" opt; do 36 | case ${opt} in 37 | e) source ${OPTARG} ;; 38 | a) access_token=${OPTARG} ;; 39 | i) query+="client_id=${OPTARG}&" ;; 40 | v) opt_verbose=1 ;; #set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 47 | 48 | 49 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 50 | declare -r EXPECTED_SCOPE="read:client_grants" 51 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 52 | 53 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 54 | 55 | curl -k -s -H "Authorization: Bearer ${access_token}" \ 56 | --url "${AUTH0_DOMAIN_URL}api/v2/client-grants?${query}" | jq '.' 57 | -------------------------------------------------------------------------------- /clients/list-clients.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-i client_id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -i id # show single client_id 22 | -1 # only first-party apps 23 | -3 # only third-party apps 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 29 | END 30 | exit $1 31 | } 32 | 33 | declare query='' 34 | 35 | while getopts "e:a:i:13hv?" opt; do 36 | case ${opt} in 37 | e) source ${OPTARG} ;; 38 | a) access_token=${OPTARG} ;; 39 | i) query="/${OPTARG}" ;; 40 | 1) query='?is_first_party=true' ;; 41 | 3) query='?is_first_party=false' ;; 42 | v) opt_verbose=1 ;; #set -x;; 43 | h | ?) usage 0 ;; 44 | *) usage 1 ;; 45 | esac 46 | done 47 | 48 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 49 | 50 | 51 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 52 | declare -r EXPECTED_SCOPE="read:clients" 53 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 54 | 55 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 56 | 57 | curl -k -s -H "Authorization: Bearer ${access_token}" \ 58 | --url "${AUTH0_DOMAIN_URL}api/v2/clients${query}" | jq '.' 59 | -------------------------------------------------------------------------------- /clients/logout_token-sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "iss": "https://abbaspour.auth0.com/", 3 | "sub": "auth0|5fadc2e53f6a96006fxxxxxx", 4 | "aud": "VJIEWAptlFWokl2pRC2ptswicxxxxx", 5 | "iat": 1674609596, 6 | "jti": "5e0fbf19-b5a1-4b68-938d-c34974933109", 7 | "events": { 8 | "http://schemas.openid.net/event/backchannel-logout": {} 9 | }, 10 | "trace_id": "78ed2efa2960aaea", 11 | "sid": "uicx6Jvc55rkdOGkQ31roOHCVjms97aD" 12 | } 13 | -------------------------------------------------------------------------------- /clients/mark-1st-party-clients.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | ### 10 | # have an `access_token` env variable with read:client and update:client scopes. 11 | # 12 | ### 13 | 14 | ./list-clients.sh -1 | jq -r '.[].client_id' | xargs -L1 -I% bash -c "./update-client-metadata.sh -i % -m 3rdparty:false; sleep 1" 15 | -------------------------------------------------------------------------------- /connections/delete-connection.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | 10 | set -eo pipefail 11 | 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 14 | 15 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 16 | 17 | 18 | 19 | function usage() { 20 | cat <&2 21 | USAGE: $0 [-e env] [-a access_token] [-i id] [-v|-h] 22 | -e file # .env file location (default cwd) 23 | -a token # access_token. default from environment variable 24 | -i id # connection id 25 | -h|? # usage 26 | -v # verbose 27 | 28 | eg, 29 | $0 -i c_123 30 | END 31 | exit $1 32 | } 33 | 34 | declare connection_id='' 35 | 36 | while getopts "e:a:i:hv?" opt; do 37 | case ${opt} in 38 | e) source ${OPTARG} ;; 39 | a) access_token=${OPTARG} ;; 40 | i) connection_id=${OPTARG} ;; 41 | v) set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 48 | 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="delete:connections" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z "${connection_id}" ]] && { echo >&2 "ERROR: connection_id undefined."; usage 1; } 55 | 56 | 57 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 58 | 59 | curl --request DELETE \ 60 | -H "Authorization: Bearer ${access_token}" \ 61 | --url "${AUTH0_DOMAIN_URL}api/v2/connections/${connection_id}" 62 | -------------------------------------------------------------------------------- /connections/list-connections.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-i connection_id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -i id # connection id 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 27 | END 28 | exit $1 29 | } 30 | 31 | declare uri='connections' 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) uri+="/${OPTARG}" ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | 47 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 48 | declare -r EXPECTED_SCOPE="read:connections" 49 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 50 | 51 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 52 | 53 | curl -s -H "Authorization: Bearer ${access_token}" \ 54 | --url ${AUTH0_DOMAIN_URL}api/v2/${uri} | jq '.' 55 | -------------------------------------------------------------------------------- /connections/templates/.gitignore: -------------------------------------------------------------------------------- 1 | atl-oidbc-bridge.js 2 | fetchUserProfile.js 3 | auth0.js 4 | -------------------------------------------------------------------------------- /connections/templates/custom-social.json: -------------------------------------------------------------------------------- 1 | { 2 | "options": { 3 | "client_id": "XXXXXX", 4 | "client_secret": "YYYYYY", 5 | "scripts": { 6 | "fetchUserProfile": "PUT `../../tools/single-line.sh fetchUserProfile.js` HERE" 7 | }, 8 | "authorizationURL": "https://some.where/oidc/oauth/authorize", 9 | "tokenURL": "https://some.where/oidc/oauth/token", 10 | "scope": "", 11 | "customHeaders": { 12 | "Authorization": "Basic XXXX" 13 | } 14 | }, 15 | "strategy": "oauth2", 16 | "name": "custom-social-connection", 17 | "is_domain_connection": true, 18 | "realms": [ 19 | "custom-social-connection" 20 | ], 21 | "enabled_clients": [] 22 | } 23 | -------------------------------------------------------------------------------- /connections/templates/fetchUserProfile-classic.js: -------------------------------------------------------------------------------- 1 | function fupClassic(access_token, ctx, callback){ 2 | 'use strict'; 3 | 4 | console.log('auth0-to-auth0 fetchUserProfile with ctx: ' + JSON.stringify(ctx)); 5 | 6 | const ruleName = 'auth0-to-auth0'; 7 | const jsonwebtoken = require('jsonwebtoken@7.1.9'); // todo: 8.4.0 8 | 9 | if (!ctx.id_token) { 10 | return callback('missing-id_token'); 11 | } 12 | 13 | const jwt = jsonwebtoken.decode(ctx.id_token); 14 | 15 | if (!jwt) { 16 | return callback('malformed-id_token'); 17 | } 18 | 19 | if (!jwt.sub) { 20 | return callback('missing-sub'); 21 | } 22 | 23 | if (!jwt.email) { 24 | return callback('missing-email'); 25 | } 26 | 27 | const profile = { 28 | user_id: jwt.sub, 29 | email: jwt.email, 30 | given_name: jwt.given_name, 31 | family_name: jwt.family_name, 32 | root_txId: 3456, 33 | user_metadata: { 34 | txId: 1234, 35 | hobby: 'surfing' 36 | }, 37 | app_metadata: { 38 | plan: 'full' 39 | } 40 | }; 41 | 42 | if (jwt.picture) { 43 | profile.picture = jwt.picture; 44 | } 45 | 46 | return callback(null, profile); 47 | } 48 | -------------------------------------------------------------------------------- /connections/templates/msv2-common.json: -------------------------------------------------------------------------------- 1 | { 2 | "strategy": "waad", 3 | "name": "msv2", 4 | "options": { 5 | "identity_api": "microsoft-identity-platform-v2.0", 6 | "useCommonEndpoint": true, 7 | "client_id": "xxxx", 8 | "client_secret": "xxxx", 9 | "tenant_domain": "Directory/tenant UUID" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /connections/templates/readme.md: -------------------------------------------------------------------------------- 1 | More templates at [oauth2-recipes](https://github.com/auth0/oauth2-recipes/tree/master/recipes) 2 | -------------------------------------------------------------------------------- /consent/introspect.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 14 | 15 | function usage() { 16 | cat <&2 17 | USAGE: $0 [-e env] [-t tenant] [-d domain] [-s state] [-x secret] [-o|-h] 18 | -e file # .env file location (default cwd) 19 | -t tenant # Auth0 tenant@region 20 | -d domain # Auth0 domain 21 | -s state # state 22 | -x secret # global client secret 23 | -a token # Token 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 -t amin01@au -s XXXXX -x YYYYYY 29 | END 30 | exit $1 31 | } 32 | 33 | declare AUTH0_DOMAIN='' 34 | declare state='' 35 | declare secret='' 36 | 37 | declare opt_verbose=0 38 | 39 | while getopts "e:t:d:s:x:hv?" opt; do 40 | case ${opt} in 41 | e) source ${OPTARG} ;; 42 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 43 | d) AUTH0_DOMAIN=${OPTARG} ;; 44 | s) state=${OPTARG} ;; 45 | x) secret=${OPTARG} ;; 46 | v) opt_verbose=1 ;; #set -x;; 47 | h | ?) usage 0 ;; 48 | *) usage 1 ;; 49 | esac 50 | done 51 | 52 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined"; usage 1; } 53 | [[ -z "${state}" ]] && { echo >&2 "ERROR: state undefined"; usage 1; } 54 | 55 | [[ -z "${secret}" ]] && { echo >&2 "ERROR: secret undefined"; usage 1; } 56 | 57 | 58 | declare -r axs_hash=$(echo -n ${state} | openssl dgst -sha256 -hmac ${secret} -binary | openssl base64) 59 | declare -r axs=$(printf "axs.alpha.%s.%s" ${state} ${axs_hash}) 60 | 61 | curl -s -X POST \ 62 | -H "Authorization: Bearer $axs" \ 63 | --url https://${AUTH0_DOMAIN}/state/introspect | jq . 64 | -------------------------------------------------------------------------------- /cookie/decode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | urldecode() { 10 | local url_encoded="${1//+/ }" 11 | printf '%b' "${url_encoded//%/\\x}" 12 | } 13 | 14 | urldecode $1 | awk -F[:.] '{print $2}' 15 | -------------------------------------------------------------------------------- /custom-domains/list-custom-domains.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { 12 | echo >&2 "error: curl not found" 13 | exit 3 14 | } 15 | command -v jq >/dev/null || { 16 | echo >&2 "error: jq not found" 17 | exit 3 18 | } 19 | 20 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 21 | 22 | function usage() { 23 | cat <&2 24 | USAGE: $0 [-e env] [-a access_token] [-i domain_id] [-v|-h] 25 | -e file # .env file location (default cwd) 26 | -a token # access_token. default from environment variable 27 | -i {id} # custom domain id 28 | -h|? # usage 29 | -v # verbose 30 | 31 | eg, 32 | $0 33 | END 34 | exit $1 35 | } 36 | 37 | declare query='' 38 | declare -i opt_verbose=0 39 | 40 | while getopts "e:a:i:hv?" opt; do 41 | case ${opt} in 42 | e) source "${OPTARG}" ;; 43 | a) access_token=${OPTARG} ;; 44 | i) query="/${OPTARG}" ;; 45 | v) opt_verbose=1 ;; #set -x;; 46 | h | ?) usage 0 ;; 47 | *) usage 1 ;; 48 | esac 49 | done 50 | 51 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 52 | 53 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 54 | declare -r EXPECTED_SCOPE="read:custom_domains" 55 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 56 | 57 | 58 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 59 | 60 | curl -k -s -H "Authorization: Bearer ${access_token}" \ 61 | --url "${AUTH0_DOMAIN_URL}api/v2/custom-domains${query}" | jq '.' 62 | -------------------------------------------------------------------------------- /delegation/.env.sample: -------------------------------------------------------------------------------- 1 | AUTH0_DOMAIN=tenant.region.auth0.com 2 | AUTH0_CLIENT_ID=XXXXXXX 3 | -------------------------------------------------------------------------------- /delegation/01-delegate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | . .env 12 | 13 | declare AUTH0_CLIENT='{"name":"auth0.js","version":"9.0.2"}' 14 | declare AUTH0_CLIENT_B64=$(echo -n $AUTH0_CLIENT | base64) 15 | 16 | declare BODY=$(cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-u user_id] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -a token # Access Token 16 | -u user_id # (optional) filter by user_id 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -u 'auth0|5b15eef91c08db5762548fd1' 22 | END 23 | exit $1 24 | } 25 | 26 | declare userId='' 27 | declare opt_verbose=0 28 | 29 | while getopts "e:a:u:hv?" opt; do 30 | case ${opt} in 31 | e) source ${OPTARG} ;; 32 | a) access_token=${OPTARG} ;; 33 | u) userId=${OPTARG} ;; 34 | h | ?) usage 0 ;; 35 | *) usage 1 ;; 36 | esac 37 | done 38 | 39 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 40 | 41 | 42 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 43 | declare -r EXPECTED_SCOPE="read:device_credentials" 44 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 45 | 46 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 47 | 48 | declare qs='' 49 | [[ -n "${userId}" ]] && qs="?user_id=${userId}" #jq_query+=" | select(.user_id | contains(\"${userId}\"))" 50 | declare -r jq_query+=".[] | \"\(.id) \(.user_id) \(.type) \(.device_name)\" " 51 | 52 | curl -s --request GET \ 53 | -H "Authorization: Bearer ${access_token}" \ 54 | --url ${AUTH0_DOMAIN_URL}api/v2/device-credentials${qs} | jq -rc "${jq_query}" | sort 55 | -------------------------------------------------------------------------------- /devices/revoke-device.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-d device_id] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -a token # Access Token 16 | -d device_id # device_id 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -d dcr_yzt4x4f76kLTXGFW 22 | END 23 | exit $1 24 | } 25 | 26 | declare device_id='' 27 | declare opt_verbose=0 28 | 29 | while getopts "e:a:d:hv?" opt; do 30 | case ${opt} in 31 | e) source ${OPTARG} ;; 32 | a) access_token=${OPTARG} ;; 33 | d) device_id=${OPTARG} ;; 34 | h | ?) usage 0 ;; 35 | *) usage 1 ;; 36 | esac 37 | done 38 | 39 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 40 | 41 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 42 | declare -r EXPECTED_SCOPE="delete:device_credentials" 43 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 44 | 45 | [[ -z "${device_id}" ]] && { echo >&2 "ERROR: device_id undefined."; usage 1; } 46 | 47 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 48 | 49 | curl -s --request DELETE \ 50 | -H "Authorization: Bearer ${access_token}" \ 51 | --url ${AUTH0_DOMAIN_URL}api/v2/device-credentials/${device_id} 52 | -------------------------------------------------------------------------------- /diagrams/co-silent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abbaspour/auth0-bash/cfae15e301d28010ab9f96995cd4e580bf5fea9c/diagrams/co-silent.png -------------------------------------------------------------------------------- /diagrams/co-silent.webseq: -------------------------------------------------------------------------------- 1 | title Cross Origin Authentication -> Auth0 2 | 3 | participant User as user 4 | participant Browser 5 | participant MyAccount WebApp \n(app.mydomain.com.au) as app 6 | participant Auth0 (IdP) \n(login.mydomain.com.au) as A0 7 | 8 | 9 | User->Browser: Navigate to \nMyAccount WebApp 10 | Browser-> +app: GET MyAccount WebApp 11 | app -> -Browser:200 Page Displayed 12 | note right of Browser: User enters email,password in the login form and submit 13 | Browser -> +A0: POST https://${AUTH0_DOMAIN}/co/authenticate {AUTH0_CLIENT_ID,email, password, realm,grant_type} 14 | A0 -> -Browser: Success ${login_ticket} 15 | Browser -> A0: GET https://${AUTH0_DOMAIN}/authorize {AUTH0_CLIENT_ID, response_type, redirect_uri, scope, audience, realm, login_ticket, state, nonce} 16 | A0 -> -Browser: Success {id_token, access_token} 17 | note right of Browser: Auth0 cookie is dropped on mydomain.com.au 18 | 19 | alt A0SESSION present and Silent Authentication for token renewal 20 | Browser-->+A0: https://${AUTH0_DOMAIN}/authorize {client_id,response_type,redirect_uri,scope,audience,connection,state,nonce,response_mode=web_message&prompt=none} 21 | A0 -> -Browser: Success {id_token, access_token} 22 | note right of Browser: checkSession 23 | end 24 | -------------------------------------------------------------------------------- /diagrams/otp-co.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abbaspour/auth0-bash/cfae15e301d28010ab9f96995cd4e580bf5fea9c/diagrams/otp-co.png -------------------------------------------------------------------------------- /diagrams/otp-co.webseq: -------------------------------------------------------------------------------- 1 | title Device Flow with Passwordless OTP 2 | 3 | participant User as u 4 | participant Auth0 as a0 5 | participant SmartTV as d 6 | participant Customer API as api 7 | 8 | opt Web Login 9 | u -> a0: signin 10 | u -> a0: link passwordless 11 | end 12 | 13 | u -> d: Open App 14 | d --> u: choose SMS or Email for OTP Activation 15 | u -> d: selects OTP target 16 | d -> a0: /passwordless/start {send:code, connection:email|sms} 17 | a0 -> u: sends OTP code 18 | 19 | u -> d: enters OTP code 20 | d -> +a0: /co/authenticate {credential_type:otp, realm:email|sms, otp:code} 21 | a0 --> -d: {login_ticket+cookie} 22 | 23 | d -> +a0: /authorize {login_ticket:ticket, cookie, scope:offline_access, response_type:code, audience:http://custom} 24 | a0 --> -d: 302 /callback?code=authz-code (no follow) 25 | 26 | d -> +a0: /oauth/token exchange (code:authz-code, client_id, client_secret|pkce_verification_code) 27 | a0 --> -d: JWT (access+id) + Opaque refresh token 28 | 29 | d -> api: /api { Authorization: Bearer access_token } 30 | 31 | opt Refresh 32 | d -> d: refresh access_token 33 | end 34 | -------------------------------------------------------------------------------- /email-template/get-template.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -t template # template name: verify_email, reset_email, welcome_email, blocked_account, stolen_credentials, enrollment_email, mfa_oob_code, change_password, password_reset 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 27 | END 28 | exit $1 29 | } 30 | 31 | declare template='' 32 | 33 | while getopts "e:a:t:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | t) template=${OPTARG} ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 47 | declare -r EXPECTED_SCOPE="read:email_templates" 48 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 49 | 50 | [[ -z "${template}" ]] && { echo >&2 "ERROR: template undefined."; usage 1; } 51 | 52 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 53 | 54 | curl -s -H "Authorization: Bearer ${access_token}" \ 55 | --url ${AUTH0_DOMAIN_URL}api/v2/email-templates/${template} | jq '.' 56 | -------------------------------------------------------------------------------- /event-streams/enable-event-stream.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2025-01-28 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-i id] [-D|-v|-h] 14 | -e file # .env file location (default cwd) 15 | -a token # access_token. default from environment variable 16 | -i id # event_stream_id 17 | -D # Disable (default is to enable) 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 23 | END 24 | exit $1 25 | } 26 | 27 | declare event_stream_id='' 28 | declare status='enabled' 29 | 30 | while getopts "e:a:i:Ehv?" opt; do 31 | case ${opt} in 32 | e) source "${OPTARG}" ;; 33 | a) access_token=${OPTARG} ;; 34 | i) event_stream_id=${OPTARG} ;; 35 | D) status='disabled' ;; 36 | v) set -x ;; 37 | h | ?) usage 0 ;; 38 | *) usage 1 ;; 39 | esac 40 | done 41 | 42 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 43 | 44 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 45 | declare -r EXPECTED_SCOPE="update:event_streams" 46 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 47 | 48 | [[ -z "${event_stream_id}" ]] && { echo >&2 "ERROR: event_stream_id undefined."; usage 1; } 49 | 50 | readonly AUTH0_DOMAIN_URL=$(echo "${access_token}" | awk -F. '{print $2}' | base64 -di 2>/dev/null | jq -r '.iss') 51 | 52 | readonly BODY="{\"status\":\"${status}\"}" 53 | 54 | curl --request PATCH \ 55 | -H "Authorization: Bearer ${access_token}" \ 56 | --header 'content-type: application/json' \ 57 | --url "${AUTH0_DOMAIN_URL}api/v2/event-streams/${event_stream_id}" \ 58 | --data "${BODY}" 59 | -------------------------------------------------------------------------------- /event-streams/list-event-streams.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2025-01-28 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-i connection_id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -i id # connection id 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 27 | END 28 | exit $1 29 | } 30 | 31 | declare uri='event-streams' 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) uri+="/${OPTARG}" ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | 47 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 48 | declare -r EXPECTED_SCOPE="read:event_streams" 49 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 50 | 51 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 52 | 53 | curl -s -H "Authorization: Bearer ${access_token}" \ 54 | --url ${AUTH0_DOMAIN_URL}api/v2/${uri} | jq '.' 55 | -------------------------------------------------------------------------------- /event-streams/webhook-cf-worker/worker.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | async fetch(request, env, ctx) { 3 | try { 4 | // Log basic details of the request 5 | console.log("Request URL:", request.url); 6 | console.log("Request Method:", request.method); 7 | console.log("Request Headers:", JSON.stringify([...request.headers])); 8 | 9 | // Clone the request to read the body safely 10 | const clonedRequest = request.clone(); 11 | 12 | // Try to parse the request body 13 | let body = null; 14 | if (request.headers.get("content-type")?.includes("application/json")) { 15 | body = await clonedRequest.json(); // Parse JSON body if content-type is application/json 16 | } else { 17 | body = await clonedRequest.text(); // Otherwise, just treat it as plain text 18 | } 19 | console.log("Request Body:", body); 20 | 21 | // Respond back with a JSON object that shows request details 22 | return new Response({}, {status: 200}); 23 | } catch (error) { 24 | console.error("Error logging request:", error); 25 | return new Response("Internal Server Error", {status: 500}); 26 | } 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /event-streams/webhook-cf-worker/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "auth0-user-events" 2 | main = "worker.mjs" 3 | compatibility_date = "2025-01-28" 4 | -------------------------------------------------------------------------------- /extensions/list.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | curl -sL https://cdn.auth0.com/extensions/extensions.json | jq -r '.[] | "\(.name) \t \(.version)"' 10 | -------------------------------------------------------------------------------- /grants/list-grants.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-u user_id] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -a token # Access Token 16 | -u user_id # (optional) filter by user_id 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -u 'auth0|5b15eef91c08db5762548fd1' 22 | END 23 | exit $1 24 | } 25 | 26 | declare userId='' 27 | declare opt_verbose=0 28 | 29 | while getopts "e:a:u:hv?" opt; do 30 | case ${opt} in 31 | e) source "${OPTARG}" ;; 32 | a) access_token=${OPTARG} ;; 33 | u) userId=${OPTARG} ;; 34 | h | ?) usage 0 ;; 35 | *) usage 1 ;; 36 | esac 37 | done 38 | 39 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 40 | 41 | 42 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 43 | declare -r EXPECTED_SCOPE="read:grants" 44 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 45 | 46 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 47 | 48 | declare qs='' 49 | [[ -n "${userId}" ]] && qs="?user_id=${userId}" #jq_query+=" | select(.user_id | contains(\"${userId}\"))" 50 | declare -r jq_query+=".[] | \"\(.id) \(.user_id) \(.audience) \(.clientID)\" " 51 | 52 | curl -s --request GET \ 53 | -H "Authorization: Bearer ${access_token}" \ 54 | --url "${AUTH0_DOMAIN_URL}api/v2/grants${qs}" | jq -rc "${jq_query}" | sort 55 | -------------------------------------------------------------------------------- /jobs/mk-import-job.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | function usage() { 6 | cat <&2 7 | USAGE: $0 [-i file] [-o file] 8 | -f file # input users CSV file 9 | -o file # output JSON file 10 | -h|? # usage 11 | -v # verbose 12 | 13 | eg, 14 | $0 -i users.csv -o users.json 15 | END 16 | exit $1 17 | } 18 | 19 | declare csv_file='' 20 | 21 | while getopts "f:o:hv?" opt 22 | do 23 | case ${opt} in 24 | f) csv_file=${OPTARG};; 25 | o) exec > ${OPTARG};; 26 | v) opt_verbose=1;; #set -x;; 27 | h|?) usage 0;; 28 | *) usage 1;; 29 | esac 30 | done 31 | 32 | [[ -z "${csv_file}" ]] && { echo >&2 "Error: missing input file"; exit 1; } 33 | 34 | cat ${csv_file} | grep -v ^# | awk -e ' 35 | BEGIN{ 36 | FS="," 37 | print "[" 38 | } 39 | 40 | END { 41 | print "]" 42 | } 43 | 44 | { 45 | customer_id=$1 46 | username=$2 47 | account_no=$2 48 | email=$3 49 | if ($3 == "") { email = sprintf("%s@my.fake.company.com",account_no) } 50 | salt_field="" 51 | if ($6 != "") { salt_field=sprintf("\"salt\": { \"value\": \"%s\", \"encoding\": \"base64\", \"position\": \"prefix\" },\n", $6) } 52 | algorithm=$5 53 | hash=$7 54 | 55 | if (NR == 1) { print "{"; } else { print ",{"; } 56 | printf " \ 57 | \"username\": \"%s\",\n \ 58 | \"email\": \"%s\",\n \ 59 | \"app_metadata\": {\n \ 60 | \"customer_id\": \"%s\",\n \ 61 | \"account_no\" : \"%s\"\n \ 62 | },\n \ 63 | \"custom_password_hash\": {\n \ 64 | \"algorithm\": \"%s\",\n \ 65 | %s \ 66 | \"hash\": { \"value\": \"%s\", \"encoding\": \"base64\" } \n \ 67 | }\n \ 68 | }\n",username, email, customer_id, account_no, algorithm, salt_field, hash 69 | }' 70 | -------------------------------------------------------------------------------- /jobs/pbkdf2-samples.md: -------------------------------------------------------------------------------- 1 | 2 | ## PBKDF2 Sample Data 3 | 4 | | Hashing | Iteration | Key Length | Salt | Password | PHC Hash | 5 | |---------|-----------|------------| ---- | ---- | ---- | 6 | | sha256 | 216000 | 32 | Y0JQSUhNcVZKUVBq | pleasework | $pbkdf2-sha256$i=216000,l=32$Y0JQSUhNcVZKUVBq$OVur66V8LRGQVMrcUznEJMrdIJvCe7JfNXTVzzyEQVE | 7 | | sha256 | 10000 | 32 | wJuJqLoUFsdXa8k3sFhRlA== | Test@123 | $pbkdf2-sha256$i=10000,l=32$wJuJqLoUFsdXa8k3sFhRlA$2waKCbPhZzL+RjWMQqvA1jpb+j56jTAXcNmRD9UTekU | 8 | | sha1 | 10000 | 20 | wJuJqLoUFsdXa8k3sFhRlA== | Test@123 | $pbkdf2-sha1$i=10000,l=20$wJuJqLoUFsdXa8k3sFhRlA$XMGVWTbeKf4Xd+CGiuEZde8x7QA | 9 | 10 | 11 | ### Gigya Example 12 | 13 | * Email - onelogintest1005@yopmail.com 14 | * Password - Test@123 15 | 16 | ```json 17 | { 18 | "password": { 19 | "hash": "XMGVWTbeKf4Xd+CGiuEZde8x7QA=", 20 | "hashSettings": { 21 | "algorithm": "pbkdf2", 22 | "rounds": 10000, 23 | "salt": "wJuJqLoUFsdXa8k3sFhRlA==" 24 | } 25 | } 26 | } 27 | ``` 28 | 29 | Matching Auth0 bulk import 30 | 31 | ```json 32 | [ 33 | { 34 | "email": "onelogintest1005@yopmail.com", 35 | "email_verified": false, 36 | "custom_password_hash": { 37 | "algorithm": "pbkdf2", 38 | "hash": { 39 | "value": "$pbkdf2-sha1$i=10000,l=20$wJuJqLoUFsdXa8k3sFhRlA$XMGVWTbeKf4Xd+CGiuEZde8x7QA", 40 | "encoding": "utf8" 41 | } 42 | } 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /jobs/pbkdf2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v node >/dev/null || { echo >&2 "error: node not found"; exit 3; } 12 | 13 | declare -i iterations=10000 14 | declare -i keylen=20 15 | declare algorithm='sha256' 16 | 17 | function usage() { 18 | cat <&2 19 | USAGE: $0 [-s salt] [-a algorithm] [-l len] [-p password] [-v|-h] 20 | -p password # password 21 | -s salt # salt (base64). defaults to a random value 22 | -i iter # iterations (defaults to $iterations) 23 | -l keylen # output key length (defaults to $keylen) 24 | -a algorithm # digest algorithm such as sha1, sha256, md, etc (defaults to $algorithm) 25 | -h|? # usage 26 | -v # verbose 27 | 28 | eg, 29 | $0 -p hardpass -s mysalt -i 10000 -l 20 -a sha1 # this is Gigya defaults 30 | END 31 | exit $1 32 | } 33 | 34 | declare password='' 35 | declare salt=$(openssl rand -base64 12) 36 | 37 | while getopts "p:s:i:l:a:hv?" opt; do 38 | case ${opt} in 39 | p) password=${OPTARG} ;; 40 | s) salt=${OPTARG} ;; 41 | i) iterations=${OPTARG} ;; 42 | l) keylen=${OPTARG} ;; 43 | a) algorithm=${OPTARG} ;; 44 | v) set -x ;; 45 | h | ?) usage 0 ;; 46 | *) usage 1 ;; 47 | esac 48 | done 49 | 50 | [[ -z "${password}" ]] && { echo >&2 "ERROR: password undefined"; usage 1; } 51 | 52 | 53 | declare -r key=$(cat </dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 14 | 15 | function usage() { 16 | cat <&2 17 | USAGE: $0 [-e file] [-f file] [-v|-h] 18 | -e file # JSON context file 19 | -f file # Liquid script file 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -e context.json -f sms.liquid 25 | END 26 | exit $1 27 | } 28 | 29 | declare contextFile='' 30 | declare liquidFile='' 31 | declare opt_verbose=0 32 | 33 | while getopts "e:f:hv?" opt; do 34 | case ${opt} in 35 | e) contextFile=${OPTARG} ;; 36 | f) liquidFile=${OPTARG} ;; 37 | v) opt_verbose=1 ;; #set -x;; 38 | h | ?) usage 0 ;; 39 | *) usage 1 ;; 40 | esac 41 | done 42 | 43 | [[ -z "${contextFile}" ]] && { echo >&2 "ERROR: Context file undefined"; usage 1; } 44 | 45 | [[ -z "${liquidFile}" ]] && { echo >&2 "ERROR: Liquid file undefined"; usage 1; } 46 | 47 | 48 | [[ -d "${DIR}/node_modules/liquidjs/" ]] || { echo >&2 "ERROR: missing module. Run: 'npm i liquidjs'" 49 | exit 2 50 | } 51 | 52 | cat <&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 18 | 19 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 20 | declare -r EXPECTED_SCOPE="read:logs" 21 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 22 | 23 | #echo "log_id,date,user_id,browser" 24 | 25 | curl -s --get -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 26 | --data-urlencode "${param_query}" \ 27 | https://${domain}/api/v2/logs | jq -r '.[] | "\(.log_id),\(.date),\(.user_id),\(.user_agent)"' 28 | -------------------------------------------------------------------------------- /logs/search.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 12 | 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-e env] [-a access_token] [-q query] [-v|-h] 16 | -e file # .env file location (default cwd) 17 | -a token # access_token. default from environment variable 18 | -q query # query 19 | -f from # log_id for retrieve logs by checkpoint 20 | -t take # The total amount of entries to retrieve when using the from parameter 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 -q type:s 26 | $0 -q 'NOT type:fsa' 27 | END 28 | exit $1 29 | } 30 | 31 | declare param_query='' 32 | 33 | while getopts "e:a:q:f:t:hv?" opt; do 34 | case ${opt} in 35 | e) source "${OPTARG}" ;; 36 | a) access_token=${OPTARG} ;; 37 | q) param_query+="&q=(${OPTARG})" ;; 38 | f) param_query+="&from=${OPTARG}" ;; 39 | t) param_query+="&take=${OPTARG}" ;; 40 | v) set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | 47 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 48 | 49 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 50 | declare -r EXPECTED_SCOPE="read:logs" 51 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 52 | 53 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 54 | 55 | curl -s --get -H "Authorization: Bearer ${access_token}" \ 56 | -H 'content-type: application/json' \ 57 | "${AUTH0_DOMAIN_URL}api/v2/logs?${param_query}" 58 | -------------------------------------------------------------------------------- /mtls.md: -------------------------------------------------------------------------------- 1 | # mTLS 2 | 3 | reference: https://docs.google.com/document/d/1E6jj11C72paoilTWWkoemqHsuuyZlhTjcfngy32gDIE/edit?usp=sharing 4 | 5 | ## Client Authentication 6 | 7 | ### 1. Get Management Access Token 8 | ```bash 9 | eval `./login/export-management-at.sh` 10 | ./jwt/dump.sh 11 | ``` 12 | 13 | Required scopes are: 14 | * `create:custom_domains` 15 | * `read:custom_domains` 16 | * `create:clients` 17 | * `update:clients` 18 | * `update:client_credentials` 19 | * `update:client_keys` 20 | * `update:tenant_settings` 21 | 22 | 23 | ### 2. Enable Custom Domain Name 24 | ```bash 25 | export CNAME_API_KEY=xxxx 26 | export EDGE_LOCATION=yyyy 27 | ``` 28 | 29 | ### 3. Enable Endpoint Aliases 30 | ```bash 31 | cd tenant 32 | ./set-tenant-flag.sh -f enable_endpoint_aliases -s true -c mtls 33 | curl -s -H "cname-api-key: ${CNAME_API_KEY}" \ 34 | https://${EDGE_LOCATION}/.well-known/openid-configuration | \ 35 | jq .mtls_endpoint_aliases 36 | ``` 37 | 38 | ### 4. Make a Self-Signed Key Pair 39 | ```bash 40 | cd ca 41 | ./self-sign.sh -n mtls-m2m 42 | ``` 43 | 44 | ### 5. Create mTLS client credentials and Patch Client to Accept it 45 | ```bash 46 | export CLIENT_ID='xxx' # create M2M client from the manage dashboard and assign audience and scopes 47 | cd clients 48 | ./create-client-credential.sh -i ${CLIENT_ID} -p ../ca/mtls-m2m-cert.pem \ 49 | -t x509_cert -n "mtls cred 1" # collect credential ID 50 | ./set-client-credential.sh -i ${CLIENT_ID} -c ${cred_xxx_from_prev_step} -t self_signed_tls_client_auth 51 | ``` 52 | 53 | ### 6. (Optional) Enable Token Binding on Client 54 | ```bash 55 | cd clients 56 | ./set-token-binding.sh -i ${CLIENT_ID} 57 | ``` 58 | 59 | ### 7. Test Exchange 60 | For CC grant 61 | ```bash 62 | cd ../login 63 | ./client-credentials.sh -i ${CLIENT_ID} -a sample.api \ 64 | -d ${EDGE_LOCATION} -n ${CNAME_API_KEY} \ 65 | -C ../ca/mtls-m2m-cert.pem 66 | ``` 67 | 68 | For ROPG 69 | ```bash 70 | ./resource-owner.sh -c "${CLIENT_ID}" -u USERNAME -p PASSWORD \ 71 | -d ${EDGE_LOCATION} -n ${CNAME_API_KEY} \ 72 | -C ../ca/mtls-m2m-cert.pem 73 | ``` 74 | 75 | ## 8. Check Token Binding (if enabled) 76 | ```bash 77 | export JWT='access_token_from_prev_step' 78 | ../jwt/dump.sh ${JWT} | jq -r '.cnf."x5t#S256"' 79 | ../ca/thumbprint.sh -f ../ca/mtls-m2m-cert.pem # two values should match 80 | ``` -------------------------------------------------------------------------------- /multifactor/.env.sample: -------------------------------------------------------------------------------- 1 | AUTH0_DOMAIN=tenant.region.auth0.com 2 | AUTH0_CLIENT_ID=XXXXXXX 3 | -------------------------------------------------------------------------------- /multifactor/authentication-method/dump-cbor-base64.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-01-23 6 | # Reference: https://webauthn.guide/ 7 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 8 | ########################################################################################## 9 | 10 | set -eo pipefail 11 | 12 | command -v base64 >/dev/null || { echo >&2 "error: base64 not found"; exit 3; } 13 | command -v hexdump >/dev/null || { echo >&2 "error: hexdump not found"; exit 3; } 14 | command -v cbor2diag >/dev/null || { echo >&2 "error: cbor2diag not found; install with: 'npm i -g cbor-cli'"; exit 3; } 15 | 16 | [[ $# -lt 1 ]] && { echo >&2 "error: no input passed in params"; exit 2; } 17 | 18 | echo "${1}" | base64 --decode | hexdump -v -e '/1 "%02X"' | xargs -0 cbor2diag -x 19 | -------------------------------------------------------------------------------- /multifactor/authentication-method/list-authentication-methods.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2023-01-23 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | declare user_id='' 17 | 18 | function usage() { 19 | cat <&2 20 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 21 | -e file # .env file location (default cwd) 22 | -a token # access_token. default from environment variable 23 | -i user_id # user_id, e.g. 'auth0|5b5fb9702e0e740478884234' 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 -i 'auth0|5b5fb9702e0e740478884234' 29 | END 30 | exit $1 31 | } 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) user_id=${OPTARG} ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 47 | declare -r EXPECTED_SCOPE="read:authentication_methods" 48 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 49 | 50 | [[ -z "${user_id}" ]] && { echo >&2 "ERROR: user_id undefined."; usage 1; } 51 | 52 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 53 | 54 | curl -s -H "Authorization: Bearer ${access_token}" \ 55 | --request GET \ 56 | --url "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}/authentication-methods" | jq . 57 | -------------------------------------------------------------------------------- /multifactor/delete-guardian-enrollment.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | declare enrollment_id='' 17 | 18 | function usage() { 19 | cat <&2 20 | USAGE: $0 [-e env] [-a access_token] [-i enrollment_id] [-v|-h] 21 | -e file # .env file location (default cwd) 22 | -a token # access_token. default from environment variable 23 | -i id # Guardian enrollment id 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 -i 'push|dev_NBFIwJ1df2rM6loH' 29 | END 30 | exit $1 31 | } 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) enrollment_id=${OPTARG} ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 47 | declare -r EXPECTED_SCOPE="delete:guardian_enrollments" 48 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 49 | 50 | [[ -z "${enrollment_id}" ]] && { echo >&2 "ERROR: enrollment_id undefined."; usage 1; } 51 | 52 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 53 | 54 | curl -s -H "Authorization: Bearer ${access_token}" \ 55 | --request DELETE \ 56 | --url "${AUTH0_DOMAIN_URL}api/v2/guardian/enrollments/${enrollment_id}" 57 | -------------------------------------------------------------------------------- /multifactor/guardian/.gitignore: -------------------------------------------------------------------------------- 1 | sns/ 2 | fcm/ 3 | apns/ 4 | apns-traffic.txt -------------------------------------------------------------------------------- /multifactor/guardian/apns/readme.md: -------------------------------------------------------------------------------- 1 | https://rajanmaharjan.medium.com/create-push-notification-platform-for-aws-sns-ae6c845735b4 2 | 3 | https://learn.microsoft.com/en-us/azure/developer/mobile-apps/notification-hubs-backend-service-flutter 4 | 5 | https://www.kodeco.com/11395893-push-notifications-tutorial-getting-started 6 | 7 | https://medium.com/zero-equals-false/generate-apns-certificate-for-ios-push-notifications-85e4a917d522 -------------------------------------------------------------------------------- /multifactor/guardian/guardian-scan-qr.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-07-13 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v zbarimg >/dev/null || { echo >&2 "error: zbarimg not found. brew install zbar"; exit 3; } 12 | 13 | readonly image_file=$(mktemp --suffix .bmp) 14 | 15 | #echo "image file: ${image_file}" 16 | readonly data=$(screencapture -i "${image_file}" && zbarimg -q --raw "${image_file}") 17 | 18 | echo "${data}" | egrep -E "enrollment_tx_id=(\w+)" -o 19 | echo "${data}" | egrep -E "secret=([^&]+)" -o 20 | -------------------------------------------------------------------------------- /multifactor/list-authenticators.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | declare user_id='' 17 | 18 | function usage() { 19 | cat <&2 20 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 21 | -e file # .env file location (default cwd) 22 | -a token # access_token. default from environment variable 23 | -i user_id # user_id, e.g. 'auth0|5b5fb9702e0e740478884234' 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 -i 'auth0|5b5fb9702e0e740478884234' 29 | END 30 | exit $1 31 | } 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) user_id=${OPTARG} ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 47 | declare -r EXPECTED_SCOPE="read:users" 48 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 49 | 50 | [[ -z "${user_id}" ]] && { echo >&2 "ERROR: user_id undefined."; usage 1; } 51 | 52 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 53 | 54 | curl -s -H "Authorization: Bearer ${access_token}" \ 55 | --request GET \ 56 | --url "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}/authenticators" 57 | -------------------------------------------------------------------------------- /multifactor/list-enrolled-authenticators.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 14 | 15 | function usage() { 16 | cat <&2 17 | USAGE: $0 [-e env] [-t tenant] [-d domain] [-m mfa_token] 18 | -e file # .env file location (default cwd) 19 | -t tenant # Auth0 tenant@region 20 | -d domain # Auth0 domain 21 | -m token # MFA token 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 -t amin01@au -m "\${mfa_token}" 27 | END 28 | exit $1 29 | } 30 | 31 | declare AUTH0_DOMAIN='' 32 | 33 | declare opt_verbose=0 34 | 35 | while getopts "e:t:d:m:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | t) AUTH0_DOMAIN=$(echo "${OPTARG}.auth0.com" | tr '@' '.') ;; 39 | d) AUTH0_DOMAIN=${OPTARG} ;; 40 | m) mfa_token=${OPTARG} ;; 41 | v) set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined"; usage 1; } 48 | [[ -z "${mfa_token}" ]] && { echo >&2 "ERROR: mfa_token undefined"; usage 1; } 49 | 50 | 51 | curl -s --request GET \ 52 | --url "https://${AUTH0_DOMAIN}/mfa/authenticators" \ 53 | --header "authorization: Bearer ${mfa_token}" \ 54 | --header 'content-type: application/x-www-form-urlencoded' | jq . 55 | -------------------------------------------------------------------------------- /multifactor/list-factors.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 26 | END 27 | exit $1 28 | } 29 | 30 | while getopts "e:a:hv?" opt; do 31 | case ${opt} in 32 | e) source ${OPTARG} ;; 33 | a) access_token=${OPTARG} ;; 34 | v) opt_verbose=1 ;; #set -x;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 41 | 42 | 43 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 44 | declare -r EXPECTED_SCOPE="read:guardian_factors" 45 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 46 | 47 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 48 | 49 | curl -s -H "Authorization: Bearer ${access_token}" \ 50 | --url ${AUTH0_DOMAIN_URL}api/v2/guardian/factors | jq '.' 51 | -------------------------------------------------------------------------------- /multifactor/list-self-authenticators.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 26 | END 27 | exit $1 28 | } 29 | 30 | while getopts "e:a:hv?" opt; do 31 | case ${opt} in 32 | e) source ${OPTARG} ;; 33 | a) access_token=${OPTARG} ;; 34 | v) opt_verbose=1 ;; #set -x;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 41 | 42 | 43 | #declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 44 | declare -r AUTH0_DOMAIN_URL='https://abbaspour.auth0.com/' 45 | 46 | curl -s -H "Authorization: Bearer ${access_token}" \ 47 | --request GET \ 48 | --url "${AUTH0_DOMAIN_URL}mfa/authenticators" 49 | -------------------------------------------------------------------------------- /multifactor/readme.md: -------------------------------------------------------------------------------- 1 | export client_id=XXXXX 2 | 3 | Enrollment Steps 4 | ================ 5 | 6 | Authenticator App 7 | ----------------- 8 | 1. ./01-start-flow.sh -t amin01@au -c $client_id -m -u email -p XXXX 9 | 2. ./02-start-associate.sh -t amin01@au -m $mfa_token -a otp 10 | 3. Open GA and scan QR code 11 | 4. ./03-complete-challenge.sh -t amin01@au -c $client_id -m $mfa_token -a otp -b OTPCODE 12 | 13 | 14 | SMS 15 | --- 16 | 1. ./01-start-flow.sh -t amin01@au -c $client_id -m -u email -p XXXX 17 | 2. ./02-start-associate.sh -t amin01@au -m $mfa_token -n +61400000000 18 | 3. Get SMS code 19 | 4. ./03-complete-challenge.sh -t amin01@au -c $client_id -m $mfa_token -a oob -o $oob_code -b SMSCODE 20 | 21 | Challenge Steps 22 | =============== 23 | 24 | Authenticator App 25 | ----------------- 26 | 1. ./01-start-flow.sh -t amin01@au -c $client_id -m -u email -p XXXX 27 | 2. ./03-complete-challenge.sh -t amin01@au -c $client_id -m $mfa_token -a otp -b OTPCODE 28 | 29 | 30 | SMS 31 | --- 32 | 1. ./01-start-flow.sh -t amin01@au -c $client_id -m -u email -p XXXX 33 | 2. ./02-mfa-challenge.sh -t amin01@au -c $client_id -m $mfa_token -a oob 34 | 3. ./03-complete-challenge.sh -t amin01@au -c $client_id -m $mfa_token -a oob -o $oob_code -b SMSCODE 35 | 36 | -------------------------------------------------------------------------------- /multifactor/remove-self-authenticators.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | declare authenticator_id='' 17 | 18 | function usage() { 19 | cat <&2 20 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 21 | -e file # .env file location (default cwd) 22 | -a token # access_token. default from environment variable 23 | -i id # authenticator id, e.g. 'totp|dev_t6eZI7yfdvT7qoko' 24 | -h|? # usage 25 | -v # verbose 26 | 27 | eg, 28 | $0 -i 'auth0|5b5fb9702e0e740478884234' 29 | END 30 | exit $1 31 | } 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) authenticator_id=${OPTARG} ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | [[ -z "${authenticator_id}" ]] && { echo >&2 "ERROR: authenticator_id undefined."; usage 1; } 47 | 48 | 49 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 50 | 51 | curl -s -H "Authorization: Bearer ${access_token}" \ 52 | --request DELETE \ 53 | --url "${AUTH0_DOMAIN_URL}mfa/authenticators/${authenticator_id}" 54 | -------------------------------------------------------------------------------- /multifactor/totp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2023-05-31 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v oathtool >/dev/null || { echo >&2 "error: oathtool not found"; exit 3; } 12 | 13 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 14 | 15 | declare secret='' 16 | 17 | function usage() { 18 | cat <&2 19 | USAGE: $0 [-s secret] [-v|-h] 20 | -s secret # base32 secret 21 | -S secret # plain secret 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 -S hellohellohello 27 | END 28 | exit $1 29 | } 30 | 31 | while getopts "e:s:S:hv?" opt; do 32 | case ${opt} in 33 | s) secret=${OPTARG} ;; 34 | S) secret=$(echo -n "${OPTARG}" | base32 -w0) ;; 35 | v) set -x;; 36 | h | ?) usage 0 ;; 37 | *) usage 1 ;; 38 | esac 39 | done 40 | 41 | [[ -z "${secret}" ]] && { echo >&2 "ERROR: secret undefined."; usage 1; } 42 | 43 | oathtool --base32 --totp "${secret}" -d 6 -------------------------------------------------------------------------------- /nss/.gitignore: -------------------------------------------------------------------------------- 1 | passwd 2 | shadow 3 | -------------------------------------------------------------------------------- /organizations/list-organizations.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2025-05-13 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { 12 | echo >&2 "error: curl not found" 13 | exit 3 14 | } 15 | command -v jq >/dev/null || { 16 | echo >&2 "error: jq not found" 17 | exit 3 18 | } 19 | 20 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 21 | 22 | function usage() { 23 | cat <&2 24 | USAGE: $0 [-e env] [-a access_token] [-i org_id] [-v|-h] 25 | -e file # .env file location (default cwd) 26 | -a token # access_token. default from environment variable 27 | -i {id} # organization id 28 | -h|? # usage 29 | -v # verbose 30 | 31 | eg, 32 | $0 33 | END 34 | exit $1 35 | } 36 | 37 | declare query='' 38 | declare -i opt_verbose=0 39 | 40 | while getopts "e:a:i:hv?" opt; do 41 | case ${opt} in 42 | e) source "${OPTARG}" ;; 43 | a) access_token=${OPTARG} ;; 44 | i) query="/${OPTARG}" ;; 45 | v) opt_verbose=1 ;; #set -x;; 46 | h | ?) usage 0 ;; 47 | *) usage 1 ;; 48 | esac 49 | done 50 | 51 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 52 | 53 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 54 | declare -r EXPECTED_SCOPE="read:organizations" 55 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 56 | 57 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 58 | 59 | curl -k -s -H "Authorization: Bearer ${access_token}" \ 60 | --url "${AUTH0_DOMAIN_URL}api/v2/organizations${query}" | jq '.' -------------------------------------------------------------------------------- /password-reset/.env.sample: -------------------------------------------------------------------------------- 1 | AUTH0_DOMAIN=tenant.region.auth0.com 2 | AUTH0_CLIENT_ID=XXXXXXX 3 | -------------------------------------------------------------------------------- /password-reset/token.sh: -------------------------------------------------------------------------------- 1 | curl -X POST -H "Authorization: Bearer $access_token" -H "Content-Type: application/json" -d '{"user_id":"auth0|5b5e65d30368302c7d1223a6"}' https://${AUTH0_DOMAIN}/api/v2/tickets/password-change 2 | -------------------------------------------------------------------------------- /passwordless/.env.sample: -------------------------------------------------------------------------------- 1 | AUTH0_DOMAIN=tenant.region.auth0.com 2 | AUTH0_CLIENT_ID=XXXXXXX 3 | -------------------------------------------------------------------------------- /passwordless/otp-verify.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OTP Verify 5 | 6 | 7 | 8 | 9 | Email 10 | SMS 11 |
12 | 13 |
14 | 15 |
16 | 17 | 18 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /prompt/get-partials.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-02-27 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-p prompt] 14 | -e file # .env file location (default cwd) 15 | -a token # access_token. default from environment variable 16 | -p prompt # prompt name 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -p customized-consent 22 | END 23 | exit ${1} 24 | } 25 | 26 | declare prompt='' 27 | declare lang='en' 28 | declare text_id='' 29 | declare text='' 30 | 31 | while getopts "e:a:p:l:s:i:t:hv?" opt; do 32 | case ${opt} in 33 | e) source "${OPTARG}" ;; 34 | a) access_token=${OPTARG} ;; 35 | p) prompt=${OPTARG} ;; 36 | l) lang=${OPTARG} ;; 37 | i) text_id=${OPTARG} ;; 38 | t) text=${OPTARG} ;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | 47 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 48 | declare -r EXPECTED_SCOPE="read:prompts" 49 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 50 | 51 | [[ -z "${prompt}" ]] && { echo >&2 "ERROR: prompt undefined."; usage 1; } 52 | 53 | readonly AUTH0_DOMAIN_URL=$(echo "${access_token}" | awk -F. '{print $2}' | base64 -di 2>/dev/null | jq -r '.iss') 54 | 55 | curl --request GET \ 56 | -H "Authorization: Bearer ${access_token}" \ 57 | --url "${AUTH0_DOMAIN_URL}api/v2/prompts/${prompt}/partials" 58 | -------------------------------------------------------------------------------- /prompt/get-render-settings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2025-01-23 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-p prompt] 14 | -e file # .env file location (default cwd) 15 | -a token # access_token. default from environment variable 16 | -p prompt # prompt name 17 | -s screen # screen name 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -p customized-consent 23 | END 24 | exit ${1} 25 | } 26 | 27 | declare prompt='' 28 | declare lang='en' 29 | declare screen='' 30 | declare text_id='' 31 | declare text='' 32 | 33 | while getopts "e:a:p:l:s:i:t:hv?" opt; do 34 | case ${opt} in 35 | e) source "${OPTARG}" ;; 36 | a) access_token=${OPTARG} ;; 37 | p) prompt=${OPTARG} ;; 38 | l) lang=${OPTARG} ;; 39 | s) screen=${OPTARG} ;; 40 | i) text_id=${OPTARG} ;; 41 | t) text=${OPTARG} ;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 48 | 49 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 50 | declare -r EXPECTED_SCOPE="read:prompts" 51 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 52 | 53 | [[ -z "${prompt}" ]] && { echo >&2 "ERROR: prompt undefined."; usage 1; } 54 | [[ -z "${screen}" ]] && { echo >&2 "ERROR: screen undefined."; usage 1; } 55 | 56 | readonly AUTH0_DOMAIN_URL=$(echo "${access_token}" | awk -F. '{print $2}' | base64 -di 2>/dev/null | jq -r '.iss') 57 | 58 | curl -s --request GET \ 59 | -H "Authorization: Bearer ${access_token}" \ 60 | --url "${AUTH0_DOMAIN_URL}api/v2/prompts/${prompt}/screen/${screen}/rendering" | jq '.' 61 | -------------------------------------------------------------------------------- /resource-server/delete-rs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | 10 | set -eo pipefail 11 | 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 14 | 15 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 16 | 17 | function usage() { 18 | cat <&2 19 | USAGE: $0 [-e env] [-a access_token] [-i id] [-v|-h] 20 | -e file # .env file location (default cwd) 21 | -a token # access_token. default from environment variable 22 | -i id # API id 23 | -h|? # usage 24 | -v # verbose 25 | 26 | eg, 27 | $0 -i 28 | END 29 | exit $1 30 | } 31 | 32 | declare api_id='' 33 | 34 | while getopts "e:a:i:hv?" opt; do 35 | case ${opt} in 36 | e) source ${OPTARG} ;; 37 | a) access_token=${OPTARG} ;; 38 | i) api_id=${OPTARG} ;; 39 | v) opt_verbose=1 ;; #set -x;; 40 | h | ?) usage 0 ;; 41 | *) usage 1 ;; 42 | esac 43 | done 44 | 45 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 46 | 47 | 48 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 49 | declare -r EXPECTED_SCOPE="delete:resource_servers" 50 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 51 | 52 | [[ -z "${api_id}" ]] && { echo >&2 "ERROR: api_id undefined."; usage 1; } 53 | 54 | 55 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 56 | 57 | curl --request DELETE \ 58 | -H "Authorization: Bearer ${access_token}" \ 59 | --url ${AUTH0_DOMAIN_URL}api/v2/resource-servers/${api_id} 60 | -------------------------------------------------------------------------------- /resource-server/list-rs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-i id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -i id # resource server id 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 27 | END 28 | exit $1 29 | } 30 | 31 | declare uri='' 32 | 33 | while getopts "e:a:i:hv?" opt; do 34 | case ${opt} in 35 | e) source ${OPTARG} ;; 36 | a) access_token=${OPTARG} ;; 37 | i) uri="/${OPTARG}" ;; 38 | v) opt_verbose=1 ;; #set -x;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 45 | 46 | 47 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 48 | declare -r EXPECTED_SCOPE="read:resource_servers" 49 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 50 | 51 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 52 | 53 | curl -s -H "Authorization: Bearer ${access_token}" \ 54 | --url ${AUTH0_DOMAIN_URL}api/v2/resource-servers${uri} | jq '.' 55 | -------------------------------------------------------------------------------- /roles/list-roles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2025-05-13 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-i role_id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -i {id} # role id 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 27 | END 28 | exit $1 29 | } 30 | 31 | declare query='' 32 | declare -i opt_verbose=0 33 | 34 | while getopts "e:a:i:hv?" opt; do 35 | case ${opt} in 36 | e) source "${OPTARG}" ;; 37 | a) access_token=${OPTARG} ;; 38 | i) query="/${OPTARG}" ;; 39 | v) opt_verbose=1 ;; #set -x;; 40 | h | ?) usage 0 ;; 41 | *) usage 1 ;; 42 | esac 43 | done 44 | 45 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 46 | 47 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 48 | declare -r EXPECTED_SCOPE="read:roles" 49 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 50 | 51 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 52 | 53 | curl -k -s -H "Authorization: Bearer ${access_token}" \ 54 | --url "${AUTH0_DOMAIN_URL}api/v2/roles${query}" | jq '.' -------------------------------------------------------------------------------- /rules/delete-rule.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] ] [-i id] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -i id # rule_id 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 -i rul_S03VwumO9S3nnxnD 27 | END 28 | exit $1 29 | } 30 | 31 | declare rule_id='' 32 | declare opt_verbose='' 33 | 34 | while getopts "e:a:f:i:hv?" opt; do 35 | case ${opt} in 36 | e) source ${OPTARG} ;; 37 | a) access_token=${OPTARG} ;; 38 | f) script_file=${OPTARG} ;; 39 | i) rule_id=${OPTARG} ;; 40 | v) opt_verbose='-v' ;; #set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 47 | 48 | 49 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 50 | declare -r EXPECTED_SCOPE="delete:rules" 51 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 52 | 53 | [[ -z "${rule_id}" ]] && { echo >&2 "ERROR: rule_id undefined."; usage 1; } 54 | 55 | 56 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 57 | 58 | curl ${opt_verbose} -X DELETE -H "Authorization: Bearer ${access_token}" \ 59 | --url ${AUTH0_DOMAIN_URL}api/v2/rules/${rule_id} 60 | -------------------------------------------------------------------------------- /rules/empty-rules/login_failure.js: -------------------------------------------------------------------------------- 1 | function (ctx, callback) { 2 | console.log('login_failure with ctx: ' + JSON.stringify(ctx)); 3 | callback(null, ctx); 4 | } 5 | -------------------------------------------------------------------------------- /rules/empty-rules/login_success.js: -------------------------------------------------------------------------------- 1 | function (user, context, callback) { 2 | console.log('login_success with user: ' + user + ', ctx: ' + JSON.stringify(ctx)); 3 | callback(null, user, context); 4 | } 5 | -------------------------------------------------------------------------------- /saml/.gitignore: -------------------------------------------------------------------------------- 1 | *.xml 2 | private_key.key 3 | -------------------------------------------------------------------------------- /saml/format-x509.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-08-19 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-t type] [-s string] [-v|-h] 14 | -t type # type of string; private or certificate (default) 15 | -s string # key string 16 | -h|? # usage 17 | -v # verbose 18 | 19 | eg, 20 | $0 -t private -s MIIEogIBAAKCAQEAp8LGsjYjsNjczgwB....KtPR8uLU= 21 | END 22 | exit $1 23 | } 24 | 25 | # Default type is certificate 26 | type="CERTIFICATE" 27 | input_string="" 28 | 29 | # Function to format the string into PEM format 30 | format_x509_string() { 31 | local header="-----BEGIN $1-----" 32 | local footer="-----END $1-----" 33 | local formatted_string=$(echo "$2" | tr -d ' ' | fold -w 64) 34 | echo -e "${header}\n${formatted_string}\n${footer}" 35 | } 36 | 37 | while getopts ":t:s:h?" opt; do 38 | case ${opt} in 39 | t) 40 | if [[ "$OPTARG" == "private" ]]; then 41 | type="PRIVATE KEY" 42 | elif [[ "$OPTARG" != "certificate" ]]; then 43 | echo "Invalid type specified. Use 'private' or 'certificate'." 44 | usage 1 45 | fi 46 | ;; 47 | s) input_string=$OPTARG;; 48 | h | \? ) usage 0;; 49 | *) usage 1 ;; 50 | esac 51 | done 52 | 53 | # Check if input string is provided 54 | if [ -z "$input_string" ]; then 55 | echo "Error: Input string (-s) is required" 56 | usage 1 57 | fi 58 | 59 | # Call the format function 60 | format_x509_string "$type" "$input_string" 61 | -------------------------------------------------------------------------------- /saml/idp-change-signing-key-action.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Handler that will be called during the execution of a PostLogin flow. 3 | * 4 | * @param {Event} event - Details about the user and the context in which they are logging in. 5 | * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login. 6 | */ 7 | exports.onExecutePostLogin = async (event, api) => { 8 | 9 | // replace with the ID of the application that has the SAML Web App Addon enabled 10 | // for which you want to change the signing key pair. 11 | const samlIdpClientId = "${samlIdpClientId}"; 12 | 13 | const signingCert = "${signingCert}"; 14 | const signingKey = "${signingKey}"; 15 | 16 | // only do this for the specific client ID. If you have multiple IdPs that require 17 | // custom certificates, you will have an "if" statement for each one. 18 | if (event.client.client_id === samlIdpClientId) { 19 | 20 | // provide your own private key and certificate here 21 | // see https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/work-with-certificates-and-keys-as-strings 22 | // for formatting instructions basically you start with a PEM format certificate and 23 | // replace the line endings with "\n" 24 | 25 | console.log(`signingCert: ${signingCert}`); 26 | 27 | api.samlResponse.setCert(signingCert); 28 | api.samlResponse.setKey(signingKey); 29 | 30 | } 31 | }; -------------------------------------------------------------------------------- /saml/idp-download-cert.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-05-20 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-t tenant] [-d domain] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -t tenant # Auth0 tenant@region 16 | -d domain # Auth0 domain 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -t amin01@au 22 | END 23 | exit $1 24 | } 25 | 26 | declare AUTH0_DOMAIN='' 27 | 28 | declare opt_verbose=0 29 | 30 | while getopts "e:t:d:c:hv?" opt; do 31 | case ${opt} in 32 | e) source ${OPTARG} ;; 33 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 34 | d) AUTH0_DOMAIN=${OPTARG} ;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined."; usage 1; } 41 | 42 | echo "Downloading to: idp-${AUTH0_DOMAIN}-cert.pem" 43 | 44 | curl -s --request GET \ 45 | -o idp-${AUTH0_DOMAIN}-cert.pem \ 46 | --url "https://${AUTH0_DOMAIN}/pem" 47 | 48 | cat "idp-${AUTH0_DOMAIN}-cert.pem" -------------------------------------------------------------------------------- /saml/idp-download-metadata.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-t tenant] [-d domain] [-c client_id] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -t tenant # Auth0 tenant@region 16 | -d domain # Auth0 domain 17 | -c client_id # Application ID with SAML Addon Enabled (i.e. IdP) 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -t amin01@au -c 62qDW3H3goXmyJTvpzQzMFGLpVGAJ1Qh 23 | END 24 | exit $1 25 | } 26 | 27 | declare AUTH0_DOMAIN='' 28 | declare AUTH0_CLIENT_ID='' 29 | 30 | declare opt_verbose=0 31 | 32 | while getopts "e:t:d:c:hv?" opt; do 33 | case ${opt} in 34 | e) source ${OPTARG} ;; 35 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 36 | d) AUTH0_DOMAIN=${OPTARG} ;; 37 | c) AUTH0_CLIENT_ID=${OPTARG} ;; 38 | h | ?) usage 0 ;; 39 | *) usage 1 ;; 40 | esac 41 | done 42 | 43 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined."; usage 1; } 44 | 45 | [[ -z "${AUTH0_CLIENT_ID}" ]] && { echo >&2 "ERROR: AUTH0_CLIENT_ID undefined."; usage 1; } 46 | 47 | echo "Downloading to: idp-${AUTH0_DOMAIN}-${AUTH0_CLIENT_ID}-metadata.xml" 48 | 49 | curl -s --request GET \ 50 | -o idp-${AUTH0_DOMAIN}-${AUTH0_CLIENT_ID}-metadata.xml \ 51 | --url "https://${AUTH0_DOMAIN}/samlp/metadata/${AUTH0_CLIENT_ID}" 52 | 53 | cat "idp-${AUTH0_DOMAIN}-${AUTH0_CLIENT_ID}-metadata.xml" -------------------------------------------------------------------------------- /saml/keycloak-idp-init.sh: -------------------------------------------------------------------------------- 1 | realm=master 2 | client=auth0 3 | host=localhost:8080 4 | 5 | open http://${host}/auth/realms/${realm}/protocol/saml/clients/${client} 6 | 7 | # open http://${host}/auth/realms/${realm}/account (personal account page) 8 | -------------------------------------------------------------------------------- /saml/replay.php: -------------------------------------------------------------------------------- 1 | 21 | 22 | 23 | 24 |
> 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /saml/saml-replay-redirect-request-static.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Replaying SAML Request 7 | 35 | 36 | 37 |

Redirecting...

38 |

If you are not redirected automatically, click here.

39 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /saml/saml-replay-response-worker.js: -------------------------------------------------------------------------------- 1 | export default { 2 | async fetch(request, env, ctx) { 3 | return handleRequest(request); 4 | } 5 | }; 6 | 7 | async function handleRequest(request) { 8 | if (request.method === 'POST') { 9 | // Parse the form data 10 | const formData = await request.formData(); 11 | const SAMLResponse = formData.get('SAMLResponse'); 12 | const RelayState = formData.get('RelayState'); 13 | 14 | if (!SAMLResponse) { 15 | return new Response('SAMLResponse parameter is missing.', { status: 400 }); 16 | } 17 | 18 | // TODO: validate Signature, Destination, and Recipient condition before posting to new Destination 19 | 20 | // Generate HTML form for redirection 21 | const redirectUrl = 'https://abbaspour.auth0.com/login/callback?connection=Amin-JP-SAML'; // Replace with your callback endpoint 22 | const html = ` 23 | 24 | 25 | 26 | 27 | Redirecting... 28 | 29 | 30 |
31 | 32 | ${RelayState ? `` : ''} 33 |
34 |

Redirecting...

35 | 36 | 37 | `; 38 | 39 | return new Response(html, { 40 | headers: { 'Content-Type': 'text/html' }, 41 | }); 42 | } else { 43 | return new Response('Method not allowed', { status: 405 }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /saml/sp-download-cert.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-05-20 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-t tenant] [-d domain] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -t tenant # Auth0 tenant@region 16 | -d domain # Auth0 domain 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -t amin01@au 22 | END 23 | exit $1 24 | } 25 | 26 | declare AUTH0_DOMAIN='' 27 | 28 | declare opt_verbose=0 29 | 30 | while getopts "e:t:d:c:hv?" opt; do 31 | case ${opt} in 32 | e) source ${OPTARG} ;; 33 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 34 | d) AUTH0_DOMAIN=${OPTARG} ;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined."; usage 1; } 41 | 42 | echo "Downloading to: sp-${AUTH0_DOMAIN}-cert.pem" 43 | 44 | curl -s --request GET \ 45 | -o sp-${AUTH0_DOMAIN}-cert.pem \ 46 | --url "https://${AUTH0_DOMAIN}/pem?cert=connection" 47 | 48 | cat "sp-${AUTH0_DOMAIN}-cert.pem" -------------------------------------------------------------------------------- /saml/sp-download-metadata.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-t tenant] [-d domain] [-c connection] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -t tenant # Auth0 tenant@region 16 | -d domain # Auth0 domain 17 | -c connection # Enterprise SAMLP connection name 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -t amin01@au -c 62qDW3H3goXmyJTvpzQzMFGLpVGAJ1Qh 23 | END 24 | exit $1 25 | } 26 | 27 | declare AUTH0_DOMAIN='' 28 | declare AUTH0_CONNECTION='' 29 | 30 | declare opt_verbose=0 31 | 32 | while getopts "e:t:d:c:hv?" opt; do 33 | case ${opt} in 34 | e) source ${OPTARG} ;; 35 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 36 | d) AUTH0_DOMAIN=${OPTARG} ;; 37 | c) AUTH0_CONNECTION=${OPTARG} ;; 38 | u) user_id=${OPTARG} ;; 39 | h | ?) usage 0 ;; 40 | *) usage 1 ;; 41 | esac 42 | done 43 | 44 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined."; usage 1; } 45 | 46 | [[ -z "${AUTH0_CONNECTION}" ]] && { echo >&2 "ERROR: AUTH0_CONNECTION undefined."; usage 1; } 47 | 48 | 49 | curl -s --request GET \ 50 | -o sp-${AUTH0_DOMAIN}-${AUTH0_CONNECTION}-metadata.xml \ 51 | --url "https://${AUTH0_DOMAIN}/samlp/metadata?connection=${AUTH0_CONNECTION}" 52 | -------------------------------------------------------------------------------- /sca.md: -------------------------------------------------------------------------------- 1 | # Strong Customer Authentication (SCA) 2 | 3 | ## Setup 4 | 1. Create a resource server or follow instructions in [Configure Rich Authorization Requests](https://auth0.com/docs/get-started/apis/configure-rich-authorization-requests) to enable consent policy 5 | 6 | ```bash 7 | ./create-rs.sh -n 'SCA Payment API' -i 'https://payments.api/' -p "transactional-authorization-with-mfa" -d payment_initiation,money_transfer 8 | ``` 9 | 10 | 2. Create a rich PAR request 11 | 12 | ```bash 13 | cd login 14 | ./authorize.sh -C -c ED27SLierWMOj8SAsTY5H87fXsq1gRLO -a 'https://payments.api/' \ 15 | -P -K ../ca/jar-test-private.pem -k qLW4Jbo7jD-e_WAFzg40aKsHTFQeGK2NT0wWnd0cCfw \ 16 | -D '[ 17 | {"type":"payment_initiation", 18 | "actions":["list_accounts","read_balances","read_transactions"], 19 | "locations":["https://example.com/accounts"] 20 | }]' 21 | 22 | ``` 23 | 24 | Sample event in Actions 25 | ```json 26 | { 27 | "transaction": { 28 | "acr_values": [], 29 | "linking_id": "mmP9ZpUWJlrO4_yGtMEO4P7STlA", 30 | "requested_authorization_details": [ 31 | { 32 | "actions": [ 33 | "list_accounts", 34 | "read_balances", 35 | "read_transactions" 36 | ], 37 | "locations": [ 38 | "https://example.com/accounts" 39 | ], 40 | "type": "payment_initiation" 41 | } 42 | ] 43 | } 44 | } 45 | ``` -------------------------------------------------------------------------------- /scim/scim-get-user.sh: -------------------------------------------------------------------------------- 1 | SCIM_ENDPOINT='https://amin.jp.auth0.com/scim/v2/connections/con_xxx' 2 | SCIM_TOKEN='xxxx' 3 | user_id='samlp|xxx|yyy' 4 | 5 | curl -H "Authorization: Bearer ${SCIM_TOKEN}" "${SCIM_ENDPOINT}/users/${user_id}" -------------------------------------------------------------------------------- /session/delete-session.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-03-20 Happy Nowruz 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i session_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i id # session id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i 'OorQtDFNK9b2YFh_xCqRfbklv_Heuydv' 25 | END 26 | exit $1 27 | } 28 | 29 | urlencode() { 30 | jq -rn --arg x "${1}" '$x|@uri' 31 | } 32 | 33 | declare session_id='' 34 | 35 | while getopts "e:a:i:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | a) access_token=${OPTARG} ;; 39 | i) session_id=$(urlencode "${OPTARG}") ;; 40 | v) set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 47 | exit 1 48 | } 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="delete:sessions" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z ${session_id} ]] && { echo >&2 "ERROR: no 'session_id' defined"; usage 1; } 55 | 56 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 57 | 58 | curl -s -X DELETE -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 59 | "${AUTH0_DOMAIN_URL}api/v2/sessions/${session_id}" | jq . 60 | -------------------------------------------------------------------------------- /session/delete-user-refresh-tokens.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-03-20 Happy Nowruz 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i user_id # user_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i 'auth0|b0dec5bdba02248abd51388' 25 | END 26 | exit $1 27 | } 28 | 29 | urlencode() { 30 | jq -rn --arg x "${1}" '$x|@uri' 31 | } 32 | 33 | declare user_id='' 34 | 35 | while getopts "e:a:i:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | a) access_token=${OPTARG} ;; 39 | i) user_id=$(urlencode "${OPTARG}") ;; 40 | v) set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 47 | exit 1 48 | } 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="delete:refresh_tokens" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z ${user_id} ]] && { echo >&2 "ERROR: no 'user_id' defined"; usage 1; } 55 | 56 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 57 | 58 | curl -s -X DELETE -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 59 | "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}/refresh-tokens" | jq . 60 | -------------------------------------------------------------------------------- /session/delete-user-sessions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-03-20 Happy Nowruz 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i user_id # user_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i 'auth0|b0dec5bdba02248abd51388' 25 | END 26 | exit $1 27 | } 28 | 29 | urlencode() { 30 | jq -rn --arg x "${1}" '$x|@uri' 31 | } 32 | 33 | declare user_id='' 34 | 35 | while getopts "e:a:i:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | a) access_token=${OPTARG} ;; 39 | i) user_id=$(urlencode "${OPTARG}") ;; 40 | v) set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 47 | exit 1 48 | } 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="delete:sessions" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z ${user_id} ]] && { echo >&2 "ERROR: no 'user_id' defined"; usage 1; } 55 | 56 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 57 | 58 | curl -s -X DELETE -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 59 | "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}/sessions" | jq . 60 | -------------------------------------------------------------------------------- /session/get-session.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-03-20 Happy Nowruz 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i session_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i id # session id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i '5_zu0EQoCPy5iHO0uIbc7VW52GeutTkh' 25 | END 26 | exit $1 27 | } 28 | 29 | urlencode() { 30 | jq -rn --arg x "${1}" '$x|@uri' 31 | } 32 | 33 | declare session_id='' 34 | 35 | while getopts "e:a:i:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | a) access_token=${OPTARG} ;; 39 | i) session_id=$(urlencode "${OPTARG}") ;; 40 | v) set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 47 | exit 1 48 | } 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="read:sessions" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z ${session_id} ]] && { echo >&2 "ERROR: no 'session_id' defined"; usage 1; } 55 | 56 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 57 | 58 | curl -s --get -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 59 | "${AUTH0_DOMAIN_URL}api/v2/sessions/${session_id}" | jq . 60 | -------------------------------------------------------------------------------- /session/list-user-refresh-tokens.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-03-20 Happy Nowruz 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i user_id # user_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i 'auth0|b0dec5bdba02248abd51388' 25 | END 26 | exit $1 27 | } 28 | 29 | urlencode() { 30 | jq -rn --arg x "${1}" '$x|@uri' 31 | } 32 | 33 | declare user_id='' 34 | 35 | while getopts "e:a:i:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | a) access_token=${OPTARG} ;; 39 | i) user_id=$(urlencode "${OPTARG}") ;; 40 | v) set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 47 | exit 1 48 | } 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="read:refresh_tokens" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z ${user_id} ]] && { echo >&2 "ERROR: no 'user_id' defined"; usage 1; } 55 | 56 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 57 | 58 | curl -s --get -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 59 | "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}/refresh-tokens" | jq . 60 | -------------------------------------------------------------------------------- /session/list-user-sessions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2024-03-20 Happy Nowruz 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -euo pipefail 10 | 11 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 12 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i user_id # user_id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 -i 'auth0|b0dec5bdba02248abd51388' 25 | END 26 | exit $1 27 | } 28 | 29 | urlencode() { 30 | jq -rn --arg x "${1}" '$x|@uri' 31 | } 32 | 33 | declare user_id='' 34 | 35 | while getopts "e:a:i:hv?" opt; do 36 | case ${opt} in 37 | e) source "${OPTARG}" ;; 38 | a) access_token=${OPTARG} ;; 39 | i) user_id=$(urlencode "${OPTARG}") ;; 40 | v) set -x;; 41 | h | ?) usage 0 ;; 42 | *) usage 1 ;; 43 | esac 44 | done 45 | 46 | [[ -z ${access_token} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 47 | exit 1 48 | } 49 | 50 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 51 | declare -r EXPECTED_SCOPE="read:sessions" 52 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 53 | 54 | [[ -z ${user_id} ]] && { echo >&2 "ERROR: no 'user_id' defined"; usage 1; } 55 | 56 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 57 | 58 | curl -s --get -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 59 | "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}/sessions" | jq . 60 | -------------------------------------------------------------------------------- /session/revoke-web-session.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 6 | 7 | function usage() { 8 | cat <&2 9 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 10 | -e file # .env file location (default cwd) 11 | -a token # access_token. default from environment variable 12 | -i user_id # user_id 13 | -s val # profile field value to set 14 | -h|? # usage 15 | -v # verbose 16 | 17 | eg, 18 | $0 -i 'auth0|b0dec5bdba02248abd51388' 19 | END 20 | exit $1 21 | } 22 | 23 | urlencode() { 24 | local length="${#1}" 25 | for ((i = 0; i < length; i++)); do 26 | local c="${1:i:1}" 27 | case $c in 28 | [a-zA-Z0-9.~_-]) printf "$c" ;; 29 | *) printf '%s' "$c" | xxd -p -c1 | 30 | while read c; do printf '%%%s' "$c"; done ;; 31 | esac 32 | done 33 | } 34 | 35 | declare user_id='' 36 | 37 | while getopts "e:a:i:hv?" opt; do 38 | case ${opt} in 39 | e) source ${OPTARG} ;; 40 | a) access_token=${OPTARG} ;; 41 | i) user_id=$(urlencode ${OPTARG}) ;; 42 | v) opt_verbose=1 ;; #set -x;; 43 | h | ?) usage 0 ;; 44 | *) usage 1 ;; 45 | esac 46 | done 47 | 48 | [[ -z "${user_id}" ]] && { echo >&2 "ERROR: no 'user_id' defined"; usage 1; } 49 | 50 | 51 | [[ -z "${access_token}" ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`"; usage 1; } 52 | 53 | 54 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 55 | 56 | declare -r email=$(curl -s --get -H "Authorization: Bearer ${access_token}" -H 'content-type: application/json' \ 57 | "${AUTH0_DOMAIN_URL}api/v2/users/${user_id}" | jq -r .email) 58 | 59 | echo "Email: ${email}" 60 | 61 | declare DATA=$(cat </dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | function usage() { 15 | cat <&2 16 | USAGE: $0 [-e env] [-a access_token] [-i profile_id] [-v|-h] 17 | -e file # .env file location (default cwd) 18 | -a token # access_token. default from environment variable 19 | -i id # self-service profile id 20 | -h|? # usage 21 | -v # verbose 22 | 23 | eg, 24 | $0 25 | END 26 | exit $1 27 | } 28 | 29 | declare uri='self-service-profiles' 30 | 31 | while getopts "e:a:i:hv?" opt; do 32 | case ${opt} in 33 | e) source "${OPTARG}" ;; 34 | a) access_token=${OPTARG} ;; 35 | i) uri+="/${OPTARG}" ;; 36 | v) set -x;; 37 | h | ?) usage 0 ;; 38 | *) usage 1 ;; 39 | esac 40 | done 41 | 42 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 43 | 44 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 45 | declare -r EXPECTED_SCOPE="read:self_service_profiles" 46 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 47 | 48 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<< "${access_token}") 49 | 50 | curl -s -H "Authorization: Bearer ${access_token}" \ 51 | --url "${AUTH0_DOMAIN_URL}api/v2/${uri}" | jq '.' 52 | -------------------------------------------------------------------------------- /tenant/cname-check.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | echo "" | openssl s_client -showcerts -connect $1:443 -servername $1 2>/dev/null | openssl x509 -text 10 | -------------------------------------------------------------------------------- /tenant/debug.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | # tenant debug flags 10 | 11 | set -eo pipefail 12 | 13 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 14 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 15 | function usage() { 16 | cat <&2 17 | USAGE: $0 [-e file] [-t tenant] [-d domain] 18 | -e file # .env file location (default cwd) 19 | -t tenant # Auth0 tenant@region 20 | -d domain # Auth0 domain 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 -t amin01@au 26 | END 27 | exit $1 28 | } 29 | 30 | declare AUTH0_DOMAIN='' 31 | 32 | while getopts "e:t:d:f:Dhv?" opt; do 33 | case ${opt} in 34 | e) source ${OPTARG} ;; 35 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 36 | d) AUTH0_DOMAIN=${OPTARG} ;; 37 | v) opt_verbose=1 ;; #set -x;; 38 | h | ?) usage 0 ;; 39 | *) usage 1 ;; 40 | esac 41 | done 42 | 43 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined"; usage 1; } 44 | 45 | curl -s https://${AUTH0_DOMAIN}/_debug | jq '.' 46 | -------------------------------------------------------------------------------- /tenant/get-tenant-settings.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 -f "enable_client_connections":true 26 | END 27 | exit $1 28 | } 29 | 30 | while getopts "e:a:hv?" opt; do 31 | case ${opt} in 32 | e) source ${OPTARG} ;; 33 | a) access_token=${OPTARG} ;; 34 | v) set -x;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 41 | 42 | 43 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 44 | declare -r EXPECTED_SCOPE="read:tenant_settings" 45 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 46 | 47 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 48 | 49 | curl -s -H "Authorization: Bearer ${access_token}" \ 50 | --url ${AUTH0_DOMAIN_URL}api/v2/tenants/settings | jq '.' 51 | -------------------------------------------------------------------------------- /tenant/list-admins.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | 14 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 15 | 16 | function usage() { 17 | cat <&2 18 | USAGE: $0 [-e env] [-a access_token] [-v|-h] 19 | -e file # .env file location (default cwd) 20 | -a token # access_token. default from environment variable 21 | -h|? # usage 22 | -v # verbose 23 | 24 | eg, 25 | $0 -n "my-tenant" 26 | END 27 | exit $1 28 | } 29 | 30 | while getopts "e:a:hv?" opt; do 31 | case ${opt} in 32 | e) source ${OPTARG} ;; 33 | a) access_token=${OPTARG} ;; 34 | v) opt_verbose=1 ;; #set -x;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE' "; usage 1; } 41 | 42 | 43 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 44 | declare -r EXPECTED_SCOPE="read:owners" 45 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 46 | 47 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 48 | 49 | curl -s -k --request GET \ 50 | -H "Authorization: Bearer ${access_token}" \ 51 | --url ${AUTH0_DOMAIN_URL}api/v2/tenants/owners | jq -r '.[] | "\(.email) \t \(.user_id)"' 52 | -------------------------------------------------------------------------------- /tenant/signing-key.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | # tenant debug flags 10 | 11 | set -eo pipefail 12 | 13 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 14 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 15 | function usage() { 16 | cat <&2 17 | USAGE: $0 [-e file] [-t tenant] [-d domain] 18 | -e file # .env file location (default cwd) 19 | -t tenant # Auth0 tenant@region 20 | -d domain # Auth0 domain 21 | -c # Connection certificate 22 | -h|? # usage 23 | -v # verbose 24 | 25 | eg, 26 | $0 -t amin01@au 27 | END 28 | exit $1 29 | } 30 | 31 | declare AUTH0_DOMAIN='' 32 | declare opt_verbose=0 33 | declare connection_cert='' 34 | 35 | while getopts "e:t:d:chv?" opt; do 36 | case ${opt} in 37 | e) source ${OPTARG} ;; 38 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 39 | d) AUTH0_DOMAIN=${OPTARG} ;; 40 | c) connection_cert=1 ;; 41 | v) opt_verbose=1 ;; #set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined"; usage 1; } 48 | 49 | declare qs='' 50 | [[ ! -z "$connection_cert" ]] && qs="?cert=connection" 51 | echo "$qs" 52 | 53 | curl -s https://${AUTH0_DOMAIN}/pem${qs} 54 | -------------------------------------------------------------------------------- /token-exchange.md: -------------------------------------------------------------------------------- 1 | ## Steps 2 | 3 | 1. get api2 AT. 4 | ```bash 5 | export access_token='HERE' 6 | ``` 7 | 8 | 2. create source RS 9 | ```bash 10 | cd resource-server 11 | ./create-rs.sh -i urn://source.api -n "Source API" 12 | ``` 13 | 14 | 3. enable TE on source API 15 | ```bash 16 | ./update-rs.sh -i source.rs.id -f token_exchange -s true 17 | ``` 18 | This returns a client_id and client_secret. We'll need them in step 5 and 8 19 | 20 | 4. Create target RS 21 | ```bash 22 | ./create-rs.sh -i urn://target.api -n "Target API" -s update:thing,read:thing 23 | ``` 24 | 25 | 5. Create Access Policy 26 | ```bash 27 | cd ../access-policy 28 | ./create-access-policy.sh -c -a urn://target.api -s read:thing 29 | ``` 30 | 31 | 6. Login with a valid user against. Can JWT.io to receive AT 32 | ```bash 33 | cd ../login 34 | ./authorize.sh -t login0@local.dev \ 35 | -c \ 36 | -R token \ 37 | -a urn://source.api \ 38 | -b firefox -o 39 | ``` 40 | 41 | 7. Login and get user's delegated AT 42 | 43 | 8. Execute exchange 44 | ```bash 45 | ./token-exchange -t login0@local.dev \ 46 | -c \ 47 | -x \ 48 | -a urn://target.api 49 | -s read:thing 50 | -i 51 | ``` 52 | -------------------------------------------------------------------------------- /token/introspect.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 14 | 15 | function usage() { 16 | cat <&2 17 | USAGE: $0 [-e env] [-t tenant] [-d domain] [-a access_token] [-o|-h] 18 | -e file # .env file location (default cwd) 19 | -t tenant # Auth0 tenant@region 20 | -d domain # Auth0 domain 21 | -c assertion # client assertion (from ${DIR}/../client-assertion.sh) 22 | -a token # Token 23 | -h|? # usage 24 | -v # verbose 25 | 26 | eg, 27 | $0 -t amin01@au -a AYnUtXXXXXX -c 'eyJ0eXAiOiJKV1QiLCJhbGciOiJ...ZD92vVGd-ZNGA' 28 | END 29 | exit $1 30 | } 31 | 32 | declare AUTH0_DOMAIN='' 33 | declare token='' 34 | 35 | declare opt_verbose=0 36 | 37 | while getopts "e:t:d:a:c:hv?" opt; do 38 | case ${opt} in 39 | e) source ${OPTARG} ;; 40 | t) AUTH0_DOMAIN=$(echo ${OPTARG}.auth0.com | tr '@' '.') ;; 41 | d) AUTH0_DOMAIN=${OPTARG} ;; 42 | a) token=${OPTARG} ;; 43 | c) client_assertion=${OPTARG} ;; 44 | v) opt_verbose=1 ;; #set -x;; 45 | h | ?) usage 0 ;; 46 | *) usage 1 ;; 47 | esac 48 | done 49 | 50 | [[ -z "${AUTH0_DOMAIN}" ]] && { echo >&2 "ERROR: AUTH0_DOMAIN undefined"; usage 1; } 51 | [[ -z "${token}" ]] && { echo >&2 "ERROR: access_token undefined"; usage 1; } 52 | 53 | 54 | declare BODY=$( cat <&2 13 | USAGE: $0 [-u username] [-l] [-v|-h] 14 | -u username # username 15 | -l # just list 16 | -p page # page (default 1) 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -u abbaspour 22 | END 23 | exit $1 24 | } 25 | 26 | declare opt_verbose=0 27 | declare username='' 28 | declare page=1 29 | 30 | declare cmd='xargs -L1 git clone' 31 | 32 | while getopts "u:p:lhv?" opt; do 33 | case ${opt} in 34 | u) username=${OPTARG} ;; 35 | p) page=${OPTARG} ;; 36 | l) cmd='tee' ;; 37 | v) opt_verbose=1 ;; #set -x;; 38 | h | ?) usage 0 ;; 39 | *) usage 1 ;; 40 | esac 41 | done 42 | 43 | [[ -z "${username}" ]] && { echo >&2 "ERROR: username undefined"; usage 1; } 44 | 45 | 46 | curl -s "https://api.github.com/users/${username}/repos?page=${page}&per_page=100" | grep -e 'git_url*' | cut -d \" -f 4 | ${cmd} 47 | -------------------------------------------------------------------------------- /tools/mk-id_token.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 6 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 7 | function usage() { 8 | cat <&2 9 | USAGE: $0 [-t tenant] [-d domain] [-i iss] [-a audience] [-s sub] [-e exp] [-n nonce] [-o file] 10 | -t tenant # tenant 11 | -d domain # domain 12 | -i iss # issuer 13 | -a aud # audience / client_id 14 | -s sub # user subject 15 | -e exp # expiry in minutes (default is 1 day) 16 | -h|? # usage 17 | -v # verbose 18 | 19 | eg, 20 | $0 -t amin01@au -a y4KJ1oOdLyx5lwILRInTbCCx221VCduh -s 'auth0|5b5e65d30368302c7d1223a6' -o id_token.json 21 | END 22 | exit $1 23 | } 24 | 25 | declare iss='' 26 | declare sub='' 27 | declare aud='' 28 | declare file='' 29 | declare nonce_field='' 30 | declare -r iat=`/bin/date +%s` 31 | declare exp=`/bin/date -v+1d +%s` 32 | declare opt_verbose=0 33 | 34 | while getopts "t:d:i:a:s:e:n:o:hv?" opt 35 | do 36 | case ${opt} in 37 | t) AUTH0_DOMAIN=`echo ${OPTARG}.auth0.com | tr '@' '.'`; iss="https://${AUTH0_DOMAIN}/";; 38 | d) iss="https://${OPTARG}/";; 39 | i) iss=${OPTARG};; 40 | a) aud=${OPTARG};; 41 | s) sub=${OPTARG};; 42 | e) exp=${OPTARG};; 43 | n) nonce_field="\"nonce\": \"${OPTARG}\",";; 44 | o) exec > ${OPTARG};; 45 | v) opt_verbose=1;; #set -x;; 46 | h|?) usage 0;; 47 | *) usage 1;; 48 | esac 49 | done 50 | 51 | [[ -z "${iss}" ]] && { echo >&2 "Error: undefined iss"; usage 1; } 52 | [[ -z "${aud}" ]] && { echo >&2 "Error: undefined aud"; usage 1; } 53 | [[ -z "${sub}" ]] && { echo >&2 "Error: undefined sub"; usage 1; } 54 | 55 | cat </dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | urlencode() { 14 | local length="${#1}" 15 | for ((i = 0; i < length; i++)); do 16 | local c="${1:i:1}" 17 | case $c in 18 | [a-zA-Z0-9.~_-]) printf "$c" ;; 19 | *) printf '%s' "$c" | xxd -p -c1 | 20 | while read c; do printf '%%%s' "$c"; done ;; 21 | esac 22 | done 23 | } 24 | 25 | urlencode $* 26 | echo 27 | -------------------------------------------------------------------------------- /tools/xml-unescape.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | function HTMLtoText() { 10 | LineOut=$1 # Parm 1= Input line 11 | LineOut="${LineOut// / }" 12 | LineOut="${LineOut//&/&}" 13 | LineOut="${LineOut//</<}" 14 | LineOut="${LineOut//>/>}" 15 | LineOut="${LineOut//"/'"'}" 16 | LineOut="${LineOut//'/"'"}" 17 | LineOut="${LineOut//“/'"'}" # TODO: ASCII/ISO for opening quote 18 | LineOut="${LineOut//”/'"'}" # TODO: ASCII/ISO for closing quote echo $LineOut 19 | } 20 | 21 | HTMLtoText "$*" 22 | -------------------------------------------------------------------------------- /twilio/.env-sample: -------------------------------------------------------------------------------- 1 | # Dashboard > Multifactor Auth > SMS 2 | TWILIO_SID=ACxxxxxxxxxx 3 | TWILIO_AUTH_TOKEN=20XXXXXXXXXXXX 4 | TWILIO_FROM=+61xyz 5 | -------------------------------------------------------------------------------- /user-blocks/list-blocks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-u user_id] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -a token # Access Token 16 | -u user_id # user id 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -u 'auth0|5b15eef91c08db5762548fd1' 22 | END 23 | exit $1 24 | } 25 | 26 | declare user_id='' 27 | declare opt_verbose=0 28 | 29 | while getopts "e:a:u:hv?" opt; do 30 | case ${opt} in 31 | e) source ${OPTARG} ;; 32 | a) access_token=${OPTARG} ;; 33 | u) user_id=${OPTARG} ;; 34 | h | ?) usage 0 ;; 35 | *) usage 1 ;; 36 | esac 37 | done 38 | 39 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE'"; usage 1; } 40 | 41 | 42 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 43 | declare -r EXPECTED_SCOPE="read:users" 44 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 45 | 46 | [[ -z "${user_id}" ]] && { echo >&2 "ERROR: user_id undefined."; usage 1; } 47 | 48 | 49 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 50 | 51 | curl -s --request GET \ 52 | -H "Authorization: Bearer ${access_token}" \ 53 | --url "${AUTH0_DOMAIN_URL}api/v2/user-blocks/${user_id}" 54 | -------------------------------------------------------------------------------- /user-blocks/unblock.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | function usage() { 12 | cat <&2 13 | USAGE: $0 [-e env] [-a access_token] [-u user_id] [-v|-h] 14 | -e file # .env file location (default cwd) 15 | -a token # Access Token 16 | -i identifer # block identifer (email, phone, username, etc) 17 | -h|? # usage 18 | -v # verbose 19 | 20 | eg, 21 | $0 -i username 22 | END 23 | exit $1 24 | } 25 | 26 | declare identifier='' 27 | declare opt_verbose=0 28 | 29 | while getopts "e:a:i:hv?" opt; do 30 | case ${opt} in 31 | e) source ${OPTARG} ;; 32 | a) access_token=${OPTARG} ;; 33 | i) identifier=${OPTARG} ;; 34 | h | ?) usage 0 ;; 35 | *) usage 1 ;; 36 | esac 37 | done 38 | 39 | [[ -z "${access_token}" ]] && { echo >&2 "ERROR: access_token undefined. export access_token='PASTE'"; usage 1; } 40 | 41 | 42 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 43 | declare -r EXPECTED_SCOPE="update:users" 44 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 45 | 46 | [[ -z "${identifier}" ]] && { echo >&2 "ERROR: identifier undefined."; usage 1; } 47 | 48 | 49 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 50 | 51 | curl -s --request DELETE -G \ 52 | -H "Authorization: Bearer ${access_token}" \ 53 | --data-urlencode "identifier=${identifier}" \ 54 | --url "${AUTH0_DOMAIN_URL}api/v2/user-blocks" 55 | -------------------------------------------------------------------------------- /users/.gitignore: -------------------------------------------------------------------------------- 1 | atl-search.sh 2 | -------------------------------------------------------------------------------- /users/block-user.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 6 | 7 | function usage() { 8 | cat <&2 9 | USAGE: $0 [-e env] [-a access_token] [-i user_id] [-v|-h] 10 | -e file # .env file location (default cwd) 11 | -a token # access_token. default from environment variable 12 | -i user_id # user_id 13 | -h|? # usage 14 | -v # verbose 15 | 16 | eg, 17 | $0 -i 'auth0|b0dec5bdba02248abd51388' 18 | END 19 | exit $1 20 | } 21 | 22 | urlencode() { 23 | local length="${#1}" 24 | for ((i = 0; i < length; i++)); do 25 | local c="${1:i:1}" 26 | case $c in 27 | [a-zA-Z0-9.~_-]) printf "$c" ;; 28 | *) printf '%s' "$c" | xxd -p -c1 | 29 | while read c; do printf '%%%s' "$c"; done ;; 30 | esac 31 | done 32 | } 33 | 34 | declare user_id='' 35 | 36 | while getopts "e:a:i:hv?" opt; do 37 | case ${opt} in 38 | e) source ${OPTARG} ;; 39 | a) access_token=${OPTARG} ;; 40 | i) user_id=$(urlencode ${OPTARG}) ;; 41 | v) opt_verbose=1 ;; #set -x;; 42 | h | ?) usage 0 ;; 43 | *) usage 1 ;; 44 | esac 45 | done 46 | 47 | [[ -z ${user_id+x} ]] && { echo >&2 "ERROR: no 'user_id' defined" 48 | exit 1 49 | } 50 | 51 | [[ -z ${access_token+x} ]] && { echo >&2 -e "ERROR: no 'access_token' defined. \nopen -a safari https://manage.auth0.com/#/apis/ \nexport access_token=\`pbpaste\`" 52 | exit 1 53 | } 54 | 55 | declare -r AVAILABLE_SCOPES=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .scope' <<< "${access_token}") 56 | declare -r EXPECTED_SCOPE="update:users" 57 | [[ " $AVAILABLE_SCOPES " == *" $EXPECTED_SCOPE "* ]] || { echo >&2 "ERROR: Insufficient scope in Access Token. Expected: '$EXPECTED_SCOPE', Available: '$AVAILABLE_SCOPES'"; exit 1; } 58 | 59 | declare -r AUTH0_DOMAIN_URL=$(jq -Rr 'split(".") | .[1] | @base64d | fromjson | .iss' <<<"${access_token}") 60 | 61 | declare DATA=$(cat < 2 | 3 | 4 | Cross Origin + Silent Authentication 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 |
16 | 17 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /users/scan-invalid-link.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # This script scans search results to find if there are any linked account with unmatched emails 6 | # Date: 2023-11-16 7 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 8 | ########################################################################################## 9 | 10 | set -eo pipefail 11 | 12 | 13 | function usage() { 14 | cat <&2 15 | USAGE: $0 [-f users.json] [-v|-h] 16 | -f users.json # user_id 17 | -o output.json # output file. default to stdout 18 | -h|? # usage 19 | -v # verbose 20 | 21 | eg, 22 | $0 -f all-users.json -o suspicious.json 23 | END 24 | exit $1 25 | } 26 | 27 | declare file='' 28 | declare output='/dev/stdout' 29 | 30 | while getopts "f:o:lshv?" opt; do 31 | case ${opt} in 32 | f) file="${OPTARG}" ;; 33 | o) output="${OPTARG}" ;; 34 | v) set -x;; 35 | h | ?) usage 0 ;; 36 | *) usage 1 ;; 37 | esac 38 | done 39 | 40 | [[ -z "${file}" ]] && { echo >&2 "ERROR: no input file defined"; usage 1; } 41 | [[ ! -f "${file}" ]] && { echo >&2 "ERROR: no input not found: ${file}"; usage 1; } 42 | 43 | jq '.[] | select(.identities | length > 1) | select (.email != .identities[1].profileData.email)' "${file}" | jq -s '.' >> "${output}" -------------------------------------------------------------------------------- /webtask/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ########################################################################################## 4 | # Author: Amin Abbaspour 5 | # Date: 2022-06-12 6 | # License: MIT (https://github.com/abbaspour/auth0-bash/blob/master/LICENSE) 7 | ########################################################################################## 8 | 9 | set -eo pipefail 10 | 11 | command -v curl >/dev/null || { echo >&2 "error: curl not found"; exit 3; } 12 | command -v jq >/dev/null || { echo >&2 "error: jq not found"; exit 3; } 13 | command -v wt >/dev/null || { echo >&2 "wt-cli not installed. run: npm install -g wt-cli"; exit 3; } 14 | 15 | readonly DIR=$(dirname "${BASH_SOURCE[0]}") 16 | 17 | function usage() { 18 | cat <&2 19 | USAGE: $0 [-e env] [-t tenant] 20 | -e file # .env file location (default cwd) 21 | -t tenant # tenant@region 22 | -8 # node v8 runtime (default) 23 | -4 # node v4 runtime (legacy) 24 | -b browser # Choose browser to open (firefox, chrome, safari) 25 | -D # Dry-run 26 | -h|? # usage 27 | -v # verbose 28 | 29 | eg, 30 | $0 -t amin01@au 31 | END 32 | exit $1 33 | } 34 | 35 | declare runtime='8' 36 | declare tenant='' 37 | declare dry='' 38 | 39 | while getopts "e:t:D48hv?" opt; do 40 | case ${opt} in 41 | e) source ${OPTARG} ;; 42 | t) tenant=${OPTARG} ;; 43 | D) dry='echo ' ;; 44 | 4) runtime='' ;; 45 | 8) runtime='8' ;; 46 | v) opt_verbose=1 ;; #set -x;; 47 | h | ?) usage 0 ;; 48 | *) usage 1 ;; 49 | esac 50 | done 51 | 52 | [[ -z "${tenant}" ]] && { echo >&2 "ERROR: tenant undefined"; usage 1; } 53 | 54 | 55 | declare -r region=$(echo ${tenant} | awk -F@ '{print $2}') 56 | declare -r container=$(echo ${tenant} | awk -F@ '{print $1}') 57 | 58 | declare sandbox="sandbox${runtime}" 59 | declare profile="${container}" 60 | 61 | [[ -n "${region}" ]] && { 62 | sandbox+="-${region}" 63 | profile+="-${region}" 64 | } 65 | 66 | #profile+="${runtime}" 67 | declare -r wt_url="https://${sandbox}.it.auth0.com" 68 | 69 | ${dry} wt init --container "${container}" --url "${wt_url}" -p "${profile}" --auth0 70 | --------------------------------------------------------------------------------