42 |
60 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/CaptchaAzureFunction/index.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios');
2 | const qs = require('qs');
3 |
4 | module.exports = async function (context, req) {
5 |
6 | // parse Basic Auth username and password
7 | var header = req.headers["authorization"] || "", // get the header
8 | token = header.split(/\s+/).pop() || "", // and the encoded auth token
9 | auth = new Buffer.from(token, "base64").toString(), // convert from base64
10 | parts = auth.split(/:/), // split on colon
11 | username = parts[0],
12 | password = parts[1];
13 |
14 | // Check for HTTP Basic Authentication, return HTTP 401 error if invalid credentials.
15 | if (
16 | username !== process.env["BASIC_AUTH_USERNAME"] ||
17 | password !== process.env["BASIC_AUTH_PASSWORD"]
18 | ) {
19 | context.res = {
20 | status: 401,
21 | };
22 | context.log("Invalid Authentication");
23 | return;
24 | }
25 |
26 | context.log('JavaScript HTTP trigger function processed a request.');
27 |
28 | let data = req.body;
29 |
30 |
31 | const extensionAttributeKey = "extension_" + process.env["B2C_EXTENSIONS_APP_ID"] + "_CaptchaUserResponseToken";
32 |
33 | let captchaToken = data && data[extensionAttributeKey]; //extension app-id
34 |
35 | // Calls Captcha API check for server-side validation of the generated token
36 | let captchaApiCheck = captchaToken && await axios.post("https://www.google.com/recaptcha/api/siteverify", qs.stringify({
37 | "secret": process.env["CAPTCHA_SECRET_KEY"],
38 | "response": captchaToken
39 | })).then(function (response) {
40 | const success = response.data.success;
41 | if (!success) {
42 | context.log("Captcha verification unsuccessful: " + JSON.stringify(response));
43 | }
44 | return success;
45 | }).catch(function (err) {
46 | context.log.error("Some other issue with Captcha API call: " + JSON.stringify(err));
47 | return false;
48 | });
49 |
50 | context.log("value of captcha check");
51 | context.log(captchaApiCheck);
52 |
53 |
54 | var body = {
55 | "version": "1.0.0",
56 | "status": 400,
57 | "action": "ValidationError",
58 | };
59 | var status = 400;
60 |
61 | if (!captchaToken) {
62 | context.log("No captcha token verification code was sent to the API.");
63 | body["userMessage"] = "Please complete the Captcha."
64 | } else if (!captchaApiCheck) {
65 | body["userMessage"] = "Invalid Captcha. Please try again."
66 | } else {
67 | status = 200;
68 | body = {
69 | "version": "1.0.0",
70 | "action": "Continue",
71 | [extensionAttributeKey]: "" //overwrites extension attribute to "" in order to not store it in the directory
72 | };
73 | }
74 |
75 | context.res = {
76 | status: status,
77 | body: body
78 | };
79 | };
--------------------------------------------------------------------------------
/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 a CAPTCHA servicein Azure AD B2C sign-up user flows."
9 | urlFragment: active-directory-node-b2c-sign-up-user-flow-captcha
10 | ---
11 |
12 | # active-directory-node-b2c-user-flow-captcha
13 |
14 | ## Contents
15 |
16 | | File/folder | Description |
17 | | --------------------------- | ------------------------------------------ |
18 | | Assets/selfAsserted.html | Sample custom HTML and JS script file for user flow. |
19 | | Assets | Contains UI/UX assets used by the user flows. |
20 | | CaptchaAzureFunction(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 | CAPTCHA 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 CAPTCHA service.
30 |
31 | Key components:
32 |
33 | - [**reCAPTCHA**](https://developers.google.com/recaptcha/) - a CAPTCHA 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 CAPTCHA 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 CAPTCHA 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 CAPTCHA challenge.
36 |
37 | This same pattern can be used for other CAPTCHA services and with other API hosting services.
38 |
39 | ## Create an API key pair for reCAPTCHA V2
40 |
41 | - Follow the [reCAPTCHA documentation](https://developers.google.com/recaptcha/intro) to create an API key pair for your scenario.
42 | - Use your Azure AD B2C tenant as the **domain**: `.b2clogin.com`
43 | - You will receive a **site_key** and **secret_key**. The values of these are referred to as **`CAPTCHA_SITE_KEY`** and **`CAPTCHA_SECRET_KEY`** in the sample code and correspond to keys used in client-side and server-side CAPTCHA API calls.
44 |
45 | ## Create a "CaptchaUserResponseToken" Custom Attribute
46 |
47 | 1. From the Azure Portal, go to **Azure AD B2C**
48 | 1. Select **User Attributes**
49 | 1. Select **Add**
50 | 1. Enter `CaptchaUserResponseToken` as the attribute **Name**
51 | 1. **Create**
52 |
53 | 
54 |
55 | Learn more about [custom attributes](https://docs.microsoft.com/azure/active-directory-b2c/user-flow-custom-attributes).
56 |
57 | ## Create a user flow
58 |
59 | This can be either be a **sign up and sign in** or a just **sign up** or user flow. Either way, the CAPTCHA will only be shown during sign up.
60 |
61 | 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.
62 | 1. In the user flow settings, navigate to **User attributes** and select the **CaptchaUserResponseToken** claim.
63 |
64 | 
65 |
66 | ## Configure custom HTML, JavaScript, and Page Layouts
67 |
68 | The **Assets > selfAsserted.html** file contains an HTML template with JavaScript (`