|
| 1 | +--- |
| 2 | +title: Secure an Azure API Management API by using Azure Active Directory B2C |
| 3 | +description: Learn how to use access tokens issued by Azure Active Directory B2C to secure an Azure API Management API endpoint. |
| 4 | +services: active-directory-b2c |
| 5 | +author: mmacy |
| 6 | +manager: celestedg |
| 7 | + |
| 8 | +ms.service: active-directory |
| 9 | +ms.workload: identity |
| 10 | +ms.topic: conceptual |
| 11 | +ms.date: 08/31/2019 |
| 12 | +ms.author: marsma |
| 13 | +ms.subservice: B2C |
| 14 | +--- |
| 15 | + |
| 16 | +# Secure an Azure API Management API with Azure AD B2C |
| 17 | + |
| 18 | +Learn how to restrict access your Azure API Management (APIM) API to clients that have authenticated with Azure Active Directory B2C (Azure AD B2C). Follow the steps in this article to create and test an inbound policy in APIM that restricts access to only those requests that include a valid Azure AD B2C-issued access token. |
| 19 | + |
| 20 | +## Prerequisites |
| 21 | + |
| 22 | +You need the following resources in place before continuing with the steps in this article: |
| 23 | + |
| 24 | +* [Azure AD B2C tenant](tutorial-create-tenant.md) |
| 25 | +* [Application registered](tutorial-register-applications.md) in your tenant |
| 26 | +* [User flows created](tutorial-create-user-flows.md) in your tenant |
| 27 | +* [Published API](../api-management/import-and-publish.md) in Azure API Management |
| 28 | +* [Postman](https://www.getpostman.com/) to test secured access (optional) |
| 29 | + |
| 30 | +## Get Azure AD B2C application ID |
| 31 | + |
| 32 | +When you secure an API in Azure API Management with Azure AD B2C, you need several values for the [inbound policy](../api-management/api-management-howto-policies.md) that you create in APIM. First, record the application ID of an application you've previously created in your Azure AD B2C tenant. If you're using the application you created in the prerequisites, use the application ID for *webbapp1*. |
| 33 | + |
| 34 | +1. Browse to your Azure AD B2C tenant in the [Azure portal](https://portal.azure.com). |
| 35 | +1. Under **Manage**, select **Applications**. |
| 36 | +1. Record the value in the **APPLICATION ID** for *webapp1* or another application you've previously created. |
| 37 | + |
| 38 | +  |
| 39 | + |
| 40 | +## Get token issuer endpoint |
| 41 | + |
| 42 | +Next, get the well-known config URL for one of your Azure AD B2C user flows. You also need the token issuer endpoint URI you want to support in Azure API Management. |
| 43 | + |
| 44 | +1. Browse to your Azure AD B2C tenant in the [Azure portal](https://portal.azure.com). |
| 45 | +1. Under **Policies**, select **User flows (policies)**. |
| 46 | +1. Select an existing policy, for example *B2C_1_signupsignin1*, then select **Run user flow**. |
| 47 | +1. Record the URL in hyperlink displayed under the **Run user flow** heading near the top of the page. This URL is the OpenID Connect well-known discovery endpoint for the user flow, and you use it in the next section when you configure the inbound policy in Azure API Management. |
| 48 | + |
| 49 | +  |
| 50 | + |
| 51 | +1. Select the hyperlink to browse to the OpenID Connect well-known configuration page. |
| 52 | +1. In the page that opens in your browser, record the `issuer` value, for example: |
| 53 | + |
| 54 | + `https://your-b2c-tenant.b2clogin.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0/` |
| 55 | + |
| 56 | + You use this value in the next section when you configure your API in Azure API Management. |
| 57 | + |
| 58 | +You should now have two URLs recorded for use in the next section: the OpenID Connect well-known configuration endpoint URL and the issuer URI. For example: |
| 59 | + |
| 60 | +``` |
| 61 | +https://yourb2ctenant.b2clogin.com/yourb2ctenant.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_signupsignin1 |
| 62 | +https://yourb2ctenant.b2clogin.com/99999999-0000-0000-0000-999999999999/v2.0/ |
| 63 | +``` |
| 64 | + |
| 65 | +## Configure inbound policy in Azure API Management |
| 66 | + |
| 67 | +You're now ready to add the inbound policy in Azure API Management that validates API calls. By adding a [JWT validation](../api-management/api-management-access-restriction-policies.md#ValidateJWT) policy that verifies the audience and issuer in an access token, you can ensure that only API calls with a valid token are accepted. |
| 68 | + |
| 69 | +1. Browse to your Azure API Management instance in the [Azure portal](https://portal.azure.com). |
| 70 | +1. Select **APIs**. |
| 71 | +1. Select the API that you want to secure with Azure AD B2C. |
| 72 | +1. Select the **Design** tab. |
| 73 | +1. Under **Inbound processing**, select **\</\>** to open the policy code editor. |
| 74 | +1. Place the following `<validate-jwt>` tag inside the `<inbound>` policy. |
| 75 | + |
| 76 | + 1. Update the `url` value in the `<openid-config>` element with your policy's well-known configuration URL. |
| 77 | + 1. Update the `<audience>` element with Application ID of the application you created previously in your B2C tenant (for example, *webapp1*). |
| 78 | + 1. Update the `<issuer>` element with the token issuer endpoint you recorded earlier. |
| 79 | + |
| 80 | + ```xml |
| 81 | + <policies> |
| 82 | + <inbound> |
| 83 | + <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid."> |
| 84 | + <openid-config url="https://yourb2ctenant.b2clogin.com/yourb2ctenant.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_signupsignin1" /> |
| 85 | + <audiences> |
| 86 | + <audience>44444444-0000-0000-0000-444444444444</audience> |
| 87 | + </audiences> |
| 88 | + <issuers> |
| 89 | + <issuer>https://yourb2ctenant.b2clogin.com/99999999-0000-0000-0000-999999999999/v2.0/</issuer> |
| 90 | + </issuers> |
| 91 | + </validate-jwt> |
| 92 | + <base /> |
| 93 | + </inbound> |
| 94 | + <backend> <base /> </backend> |
| 95 | + <outbound> <base /> </outbound> |
| 96 | + <on-error> <base /> </on-error> |
| 97 | + </policies> |
| 98 | + ``` |
| 99 | + |
| 100 | +## Validate secure API access |
| 101 | + |
| 102 | +To ensure only authenticated callers can access your API, you can validate your Azure API Management configuration by calling the API with [Postman](https://www.getpostman.com/). |
| 103 | + |
| 104 | +To call the API, you need both an access token issued by Azure AD B2C, and an APIM subscription key. |
| 105 | + |
| 106 | +### Get an access token |
| 107 | + |
| 108 | +You first need a token issued by Azure AD B2C to use in the `Authorization` header in Postman. You can get one by using the **Run now** feature of your sign-up/sign-in user flow you should have created as one of the prerequisites. |
| 109 | + |
| 110 | +1. Browse to your Azure AD B2C tenant in the [Azure portal](https://portal.azure.com). |
| 111 | +1. Under **Policies**, select **User flows (policies)**. |
| 112 | +1. Select an existing sign-up/sign-in user flow, for example *B2C_1_signupsignin1*. |
| 113 | +1. For **Application**, select *webapp1*. |
| 114 | +1. For **Reply URL**, choose `https://jwt.ms`. |
| 115 | +1. Select **Run user flow**. |
| 116 | + |
| 117 | +  |
| 118 | + |
| 119 | +1. Complete the sign-in process. You should be redirected to `https://jwt.ms`. |
| 120 | +1. Record the encoded token value displayed in your browser. You use this token value for the Authorization header in Postman. |
| 121 | + |
| 122 | +  |
| 123 | + |
| 124 | +### Get API subscription key |
| 125 | + |
| 126 | +A client application (in this case, Postman) that calls a published API must include a valid API Management subscription key in its HTTP requests to the API. To get a subscription key to include in your Postman HTTP request: |
| 127 | + |
| 128 | +1. Browse to your Azure API Management service instance in the [Azure portal](https://portal.azure.com). |
| 129 | +1. Select **Subscriptions**. |
| 130 | +1. Select the ellipsis for **Product: Unlimited**, then select **Show/hide keys**. |
| 131 | +1. Record the **PRIMARY KEY** for the product. You use this key for the `Ocp-Apim-Subscription-Key` header in your HTTP request in Postman. |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | +### Test a secure API call |
| 136 | + |
| 137 | +With the access token and APIM subscription key recorded, you're now ready to test whether you've correctly configured secure access to the API. |
| 138 | + |
| 139 | +1. Create a new `GET` request in [Postman](https://www.getpostman.com/). For the request URL, specify the speakers list endpoint of the API you published as one of the prerequisites. For example: |
| 140 | + |
| 141 | + `https://contosoapim.azure-api.net/conference/speakers` |
| 142 | + |
| 143 | +1. Next, add the following headers: |
| 144 | + |
| 145 | + | Key | Value | |
| 146 | + | --- | ----- | |
| 147 | + | `Authorization` | Encoded token value you recorded earlier, prefixed with `Bearer ` (include the space after "Bearer") | |
| 148 | + | `Ocp-Apim-Subscription-Key` | APIM subscription key you recorded earlier | |
| 149 | + |
| 150 | + Your **GET** request URL and **Headers** should appear similar to: |
| 151 | + |
| 152 | +  |
| 153 | + |
| 154 | +1. Select the **Send** button in Postman to execute the request. If you've configured everything correctly, you should be presented with a JSON response with a collection of conference speakers (shown here truncated): |
| 155 | + |
| 156 | + ```JSON |
| 157 | + { |
| 158 | + "collection": { |
| 159 | + "version": "1.0", |
| 160 | + "href": "https://conferenceapi.azurewebsites.net:443/speakers", |
| 161 | + "links": [], |
| 162 | + "items": [ |
| 163 | + { |
| 164 | + "href": "https://conferenceapi.azurewebsites.net/speaker/1", |
| 165 | + "data": [ |
| 166 | + { |
| 167 | + "name": "Name", |
| 168 | + "value": "Scott Guthrie" |
| 169 | + } |
| 170 | + ], |
| 171 | + "links": [ |
| 172 | + { |
| 173 | + "rel": "http://tavis.net/rels/sessions", |
| 174 | + "href": "https://conferenceapi.azurewebsites.net/speaker/1/sessions" |
| 175 | + } |
| 176 | + ] |
| 177 | + }, |
| 178 | + [...] |
| 179 | + ``` |
| 180 | + |
| 181 | +### Test an insecure API call |
| 182 | + |
| 183 | +Now that you've made a successful request, test the failure case to ensure that calls to your API with an *invalid* token are rejected as expected. One way to perform the test is to add or change a few characters in the token value, then execute the same `GET` request as before. |
| 184 | + |
| 185 | +1. Add several characters to the token value to simulate an invalid token. For example, add "INVALID" to the token value: |
| 186 | + |
| 187 | +  |
| 188 | + |
| 189 | +1. Select the **Send** button to execute the request. With an invalid token, the expected result is a `401` unauthorized status code: |
| 190 | + |
| 191 | + ```JSON |
| 192 | + { |
| 193 | + "statusCode": 401, |
| 194 | + "message": "Unauthorized. Access token is missing or invalid." |
| 195 | + } |
| 196 | + ``` |
| 197 | + |
| 198 | +If you see the `401` status code, you've verified that only callers with a valid access token issued by Azure AD B2C can make successful requests to your Azure API Management API. |
| 199 | + |
| 200 | +## Support multiple applications and issuers |
| 201 | + |
| 202 | +Several applications typically interact with a single REST API. To allow multiple applications to call your API, add their application IDs to the `<audiences>` element in the APIM inbound policy. |
| 203 | + |
| 204 | +```XML |
| 205 | +<!-- Accept requests from multiple applications --> |
| 206 | +<audiences> |
| 207 | + <audience>44444444-0000-0000-0000-444444444444</audience> |
| 208 | + <audience>66666666-0000-0000-0000-666666666666</audience> |
| 209 | +</audiences> |
| 210 | +``` |
| 211 | + |
| 212 | +Similarly, to support multiple token issuers, add their endpoint URIs to the `<audiences>` element in the APIM inbound policy. |
| 213 | + |
| 214 | +```XML |
| 215 | +<!-- Accept tokens from multiple issuers --> |
| 216 | +<issuers> |
| 217 | + <issuer>https://yourb2ctenant.b2clogin.com/99999999-0000-0000-0000-999999999999/v2.0/</issuer> |
| 218 | + <issuer>https://login.microsoftonline.com/99999999-0000-0000-0000-999999999999/v2.0/</issuer> |
| 219 | +</issuers> |
| 220 | +``` |
| 221 | + |
| 222 | +## Migrate to b2clogin.com |
| 223 | + |
| 224 | +If you have an APIM API that validates tokens issued by the legacy `login.microsoftonline.com` endpoint, you should migrate the API and the applications that call it to use tokens issued by [b2clogin.com](b2clogin.md). |
| 225 | + |
| 226 | +You can follow this general process to perform a staged migration: |
| 227 | + |
| 228 | +1. Add support in your APIM inbound policy for tokens issued by both b2clogin.com and login.microsoftonline.com. |
| 229 | +1. Update your applications one at a time to obtain tokens from the b2clogin.com endpoint. |
| 230 | +1. Once all of your applications are correctly obtaining tokens from b2clogin.com, remove support for login.microsoftonline.com-issued tokens from the API. |
| 231 | + |
| 232 | +The following example APIM inbound policy illustrates how to accept tokens issued by both b2clogin.com and login.microsoftonline.com. Additionally, it supports API requests from two applications. |
| 233 | + |
| 234 | +```XML |
| 235 | +<policies> |
| 236 | + <inbound> |
| 237 | + <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid."> |
| 238 | + <openid-config url="https://yourb2ctenant.b2clogin.com/yourb2ctenant.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_signupsignin1" /> |
| 239 | + <audiences> |
| 240 | + <audience>44444444-0000-0000-0000-444444444444</audience> |
| 241 | + <audience>66666666-0000-0000-0000-666666666666</audience> |
| 242 | + </audiences> |
| 243 | + <issuers> |
| 244 | + <issuer>https://login.microsoftonline.com/99999999-0000-0000-0000-999999999999/v2.0/</issuer> |
| 245 | + <issuer>https://yourb2ctenant.b2clogin.com/99999999-0000-0000-0000-999999999999/v2.0/</issuer> |
| 246 | + </issuers> |
| 247 | + </validate-jwt> |
| 248 | + <base /> |
| 249 | + </inbound> |
| 250 | + <backend> <base /> </backend> |
| 251 | + <outbound> <base /> </outbound> |
| 252 | + <on-error> <base /> </on-error> |
| 253 | +</policies> |
| 254 | +``` |
| 255 | + |
| 256 | +## Next steps |
| 257 | + |
| 258 | +For additional details on Azure API Management policies, see the [APIM policy reference index](../api-management/api-management-policies.md). |
| 259 | + |
| 260 | +You can find information about migrating OWIN-based web APIs and their applications to b2clogin.com in [Migrate an OWIN-based web API to b2clogin.com](multiple-token-endpoints.md). |
0 commit comments