├── ArkoseLabsAzureFunction ├── sample.dat ├── function.json └── index.js ├── Assets ├── logo.png ├── background.jpg ├── selfAsserted.html └── global.css ├── ReadmeImages ├── .DS_Store ├── configure_page_layouts.png ├── create-api-connector.png ├── custom-attribute-add.png ├── enable-api-connector.png ├── select-custom-attribute.png └── search-for-extensions-app-id.png ├── package.json ├── host.json ├── .github ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── LICENSE.md ├── .gitignore ├── SECURITY.md ├── CONTRIBUTING.md └── README.md /ArkoseLabsAzureFunction/sample.dat: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Azure" 3 | } -------------------------------------------------------------------------------- /Assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/Assets/logo.png -------------------------------------------------------------------------------- /Assets/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/Assets/background.jpg -------------------------------------------------------------------------------- /ReadmeImages/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/ReadmeImages/.DS_Store -------------------------------------------------------------------------------- /ReadmeImages/configure_page_layouts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/ReadmeImages/configure_page_layouts.png -------------------------------------------------------------------------------- /ReadmeImages/create-api-connector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/ReadmeImages/create-api-connector.png -------------------------------------------------------------------------------- /ReadmeImages/custom-attribute-add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/ReadmeImages/custom-attribute-add.png -------------------------------------------------------------------------------- /ReadmeImages/enable-api-connector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/ReadmeImages/enable-api-connector.png -------------------------------------------------------------------------------- /ReadmeImages/select-custom-attribute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/ReadmeImages/select-custom-attribute.png -------------------------------------------------------------------------------- /ReadmeImages/search-for-extensions-app-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/active-directory-b2c-node-sign-up-user-flow-arkose/main/ReadmeImages/search-for-extensions-app-id.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "captcha-b2c-sign-up-node", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "start": "func start", 7 | "test": "echo \"No tests yet...\"" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.19.2" 11 | }, 12 | "devDependencies": {} 13 | } 14 | -------------------------------------------------------------------------------- /ArkoseLabsAzureFunction/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "bindings": [ 3 | { 4 | "authLevel": "function", 5 | "type": "httpTrigger", 6 | "direction": "in", 7 | "name": "req", 8 | "methods": [ 9 | "post" 10 | ] 11 | }, 12 | { 13 | "type": "http", 14 | "direction": "out", 15 | "name": "res" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "extensionBundle": { 4 | "id": "Microsoft.Azure.Functions.ExtensionBundle", 5 | "version": "[1.*, 2.0.0)" 6 | }, 7 | "logging": { 8 | "fileLoggingMode": "always", 9 | "logLevel": { 10 | "default": "Information", 11 | "Host.Results": "Error", 12 | "Function": "Trace", 13 | "Host.Aggregator": "Trace" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 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 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (https://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | .env.test 64 | 65 | # parcel-bundler cache (https://parceljs.org/) 66 | .cache 67 | 68 | # next.js build output 69 | .next 70 | 71 | # nuxt.js build output 72 | .nuxt 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless/ 79 | 80 | # FuseBox cache 81 | .fusebox/ 82 | 83 | # DynamoDB Local files 84 | .dynamodb/ 85 | 86 | # TypeScript output 87 | dist 88 | out 89 | 90 | # Azure Functions artifacts 91 | bin 92 | obj 93 | appsettings.json 94 | local.settings.json 95 | 96 | # Other 97 | *.DS_Store* 98 | 99 | # Visual Studio Code 100 | .vscode/ -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | -------------------------------------------------------------------------------- /ArkoseLabsAzureFunction/index.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | 3 | module.exports = async function (context, req) { 4 | 5 | // parse Basic Auth username and password 6 | var header = req.headers["authorization"] || "", // get the header 7 | token = header.split(/\s+/).pop() || "", // and the encoded auth token 8 | auth = new Buffer.from(token, "base64").toString(), // convert from base64 9 | parts = auth.split(/:/), // split on colon 10 | username = parts[0], 11 | password = parts[1]; 12 | 13 | // Check for HTTP Basic Authentication, return HTTP 401 error if invalid credentials. 14 | if ( 15 | username !== process.env["BASIC_AUTH_USERNAME"] || 16 | password !== process.env["BASIC_AUTH_PASSWORD"] 17 | ) { 18 | context.res = { 19 | status: 401, 20 | }; 21 | context.log("Invalid Authentication"); 22 | return; 23 | } 24 | 25 | context.log('JavaScript HTTP trigger function processed a request.'); 26 | 27 | let data = req.body; 28 | 29 | const extensionAttributeKey = "extension_" + process.env["B2C_EXTENSIONS_APP_ID"] + "_ArkoseSessionToken"; 30 | let arkoseSessionToken = data && data[extensionAttributeKey]; //extension app-id 31 | 32 | context.log("value of token"); 33 | context.log(arkoseSessionToken); 34 | 35 | // Calls Captcha API check for server-side validation of the generated token 36 | let arkoseVerifyAPI = arkoseSessionToken && await axios.post("https://verify-api.arkoselabs.com/api/v3/verify/", { 37 | "private_key": process.env["ARKOSE_PRIVATE_KEY"], 38 | "session_token": arkoseSessionToken, 39 | }).then(function (response) { 40 | context.log(response.data); 41 | const success = response.data.session_is_legit > 0; 42 | if (!success) { 43 | context.log("unsuccessful!"); 44 | } 45 | return success; 46 | }).catch(function (err) { 47 | context.log.error("Some other issue with verification API call: " + JSON.stringify(err)); 48 | return false; 49 | }); 50 | 51 | context.log("value of verification check resolution"); 52 | context.log(arkoseVerifyAPI); 53 | 54 | var body = {}; 55 | var status = 200; 56 | 57 | if (!arkoseSessionToken){ 58 | body = { 59 | "version": "1.0.0", 60 | "action": "ValidationError", 61 | "status": 400, 62 | "userMessage": "Please complete the puzzle so we know you are a real person." 63 | } 64 | status = 400; 65 | } else if (!arkoseVerifyAPI) { 66 | body = { 67 | "version": "1.0.0", 68 | "action": "ShowBlockPage", 69 | "userMessage": "There was an error with your request. Please try again if you believe this is an error." 70 | } 71 | } else { 72 | body = { 73 | "version": "1.0.0", 74 | "action": "Continue", 75 | [extensionAttributeKey]: "", 76 | } 77 | } 78 | 79 | context.res = { 80 | status: status, 81 | body: body 82 | }; 83 | }; -------------------------------------------------------------------------------- /Assets/selfAsserted.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sign in 5 | 6 | 7 | 8 | 9 | 14 | 15 | 20 | 21 | 27 | 28 | 34 | 35 | 36 |
37 |
38 |
39 |
40 |
41 |
42 | 47 |
48 |

Sign up for a new account

49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to [project-title] 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 6 | 7 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 14 | 15 | - [Code of Conduct](#coc) 16 | - [Issues and Bugs](#issue) 17 | - [Feature Requests](#feature) 18 | - [Submission Guidelines](#submit) 19 | 20 | ## Code of Conduct 21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | 23 | ## Found an Issue? 24 | If you find a bug in the source code or a mistake in the documentation, you can help us by 25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Want a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | 33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 34 | 35 | ## Submission Guidelines 36 | 37 | ### Submitting an Issue 38 | Before you submit an issue, search the archive, maybe your question was already answered. 39 | 40 | If your issue appears to be a bug, and hasn't been reported, open a new issue. 41 | Help us to maximize the effort we can spend fixing issues and adding new 42 | features, by not reporting duplicate issues. Providing the following information will increase the 43 | chances of your issue being dealt with quickly: 44 | 45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 46 | * **Version** - what version is affected (e.g. 0.1.2) 47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 48 | * **Browsers and Operating System** - is this a problem with all browsers? 49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps 50 | * **Related Issues** - has a similar issue been reported before? 51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be 52 | causing the problem (line of code or commit) 53 | 54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new]. 55 | 56 | ### Submitting a Pull Request (PR) 57 | Before you submit your Pull Request (PR) consider the following guidelines: 58 | 59 | * Search the repository (https://github.com/[organization-name]/[repository-name]/pulls) for an open or closed PR 60 | that relates to your submission. You don't want to duplicate effort. 61 | 62 | * Make your changes in a new git fork: 63 | 64 | * Commit your changes using a descriptive commit message 65 | * Push your fork to GitHub: 66 | * In GitHub, create a pull request 67 | * If we suggest changes then: 68 | * Make the required updates. 69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 70 | 71 | ```shell 72 | git rebase master -i 73 | git push -f 74 | ``` 75 | 76 | That's it! Thank you for your contribution! 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | languages: 4 | - javascript 5 | - nodejs 6 | products: 7 | - azure-active-directory 8 | description: A sample to demonstrate how to use Arkose Lab's fraud and abuse protection in Azure AD B2C sign-up user flows. 9 | urlFragment: active-directory-node-b2c-sign-up-user-flow-arkose 10 | --- 11 | 12 | # active-directory-node-b2c-user-flow-arkose 13 | 14 | ## Contents 15 | 16 | | File/folder | Description | 17 | | --------------------------- | ------------------------------------------ | 18 | | [Assets/selfAsserted.html](selfAsserted.html) | Sample custom HTML and JS script file for user flow. | 19 | | [Assets](selfAsserted.html) | Contains UI/UX assets used by the user flows. | 20 | | [ArkoseAzureFunction](AzureFunction.cs) | Sample source code for Node.js HTTP trigger. | 21 | | `README.md` | This README file. | 22 | | `.gitignore` | Define what to ignore at commit time. | 23 | | `CONTRIBUTING.md` | Guidance on how to contribute to this repository. | 24 | | `LICENSE.md` | The license for the sample. | 25 | | `SECURITY.md` | The security notice for the sample. | 26 | 27 | ## Key Concepts 28 | 29 | Arkose services are often used in authentication scenarios to protect against bots or other automated abuse. This sample demonstrates how to integrate an Azure AD B2C sign-up user flow with a Arkose service. 30 | 31 | Key components: 32 | 33 | - [**Arkose Labs**](https://www.arkoselabs.com/) - an fraud and abuse service for protecting against bots and other automated abuse. 34 | - **Azure AD B2C sign-up user flow** - The sign-up experience that will be using the Arkose Labs service. Will utilize the [custom HTML & JavaScript](https://docs.microsoft.com/azure/active-directory-b2c/customize-ui-overview) and [API connectors](https://docs.microsoft.com/azure/active-directory-b2c/api-connectors-overview) to integrate with the Arkose service. 35 | - **Azure Functions** - API endpoint hosted by you that works in conjunction with the **API connectors** feature. This API is responsible for doing the server-side validation of the Arkose session token. 36 | 37 | This same pattern can be used with other API hosting and automated fraud protection services. 38 | 39 | ## Get an API key pair for Arkose Labs 40 | 41 | - Engage with Arkose Labs to acquire an account and public and private keys. 42 | - You will receive a **public key** and a **private key**. The values of these are referred to as **`ARKOSE_PUBLIC_KEY`** and **`ARKOSE_PRIVATE_KEY`** in the sample code and this documentation. They correspond to keys used in client-side and server-side components. 43 | 44 | ## Create a "ArkoseSessionToken" Custom Attribute 45 | 46 | 1. From the Azure Portal, go to **Azure AD B2C** 47 | 1. Select **User Attributes** 48 | 1. Select **Add** 49 | 1. Enter `ArkoseSessionToken` as the attribute **Name** 50 | 1. **Create** 51 | 52 | ![Custom attribute creation](ReadmeImages/custom-attribute-add.png) 53 | 54 | Learn more about [custom attributes](https://docs.microsoft.com/azure/active-directory-b2c/user-flow-custom-attributes). 55 | 56 | ## Create a user flow 57 | 58 | This can be either be a **sign up and sign in** or a just **sign up** or user flow. Either way, the Arkose will only be shown during sign up. 59 | 60 | 1. [Follow these instructions](https://docs.microsoft.com/azure/active-directory-b2c/tutorial-create-user-flows). If using an existing user flow, note that user flows must be of the "Recommended (next-generation preview)" version type. 61 | 1. In the user flow settings, navigate to **User attributes** and select the **ArkoseSessionToken** claim. 62 | 63 | ![Select custom attribute in user flow](ReadmeImages/select-custom-attribute.png) 64 | 65 | ## Configure custom HTML, JavaScript, and Page Layouts 66 | 67 | The **Assets > selfAsserted.html** file contains an HTML template with JavaScript (`