Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying $aadToken audience #161

Merged
merged 3 commits into from
Mar 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ REST Client allows you to send HTTP request and view the response in Visual Stud
- Support both __environment__ and __file__ custom variables
- Auto completion and hover support for both environment and file custom variables
- Go to definition and find all references support _ONLY_ for file custom variables
- Provide system dynamic variables `{{$guid}}`, `{{$randomInt min max}}`, `{{$timestamp}}`, and `{{$aadToken [new] [public|cn|de|us|ppe] [<domain|tenantId>]}}`
- Provide system dynamic variables `{{$guid}}`, `{{$randomInt min max}}`, `{{$timestamp}}`, and `{{$aadToken [new] [public|cn|de|us|ppe] [<domain|tenantId>] [aud:<domain|tenantId>]}}`
- Easily create/update/delete environments and custom variables in setting file
- Support environment switch
- Support shared environment to provide variables that available in all environments
Expand Down Expand Up @@ -370,14 +370,16 @@ Content-Type: application/json

### Global Variables
Global variables provide a pre-defined set of variables that can be used in any part of the request(Url/Headers/Body) in the format `{{$variableName}}`. Currently, we provide a few dynamic variables which you can use in your requests. The variable names are _case-sensitive_.
* `{{$aadToken [new] [public|cn|de|us|ppe] [<domain|tenantId>]}}`: Add an Azure Active Directory token based on the following options (must be specified in order):
* `{{$aadToken [new] [public|cn|de|us|ppe] [<domain|tenantId>] [aud:<domain|tenantId>]}}`: Add an Azure Active Directory token based on the following options (must be specified in order):

`new`: Optional. Specify `new` to force re-authentication and get a new token for the specified directory. Default: Reuse previous token for the specified directory from an in-memory cache. Expired tokens are refreshed automatically. (Use `F1 > Rest Client: Clear Azure AD Token Cache` or restart Visual Studio Code to clear the cache.)

`public|cn|de|us|ppe`: Optional. Specify top-level domain (TLD) to get a token for the specified government cloud, `public` for the public cloud, or `ppe` for internal testing. Default: TLD of the REST endpoint; `public` if not valid.

`<domain|tenantId>`: Optional. Domain or tenant id for the directory to sign in to. Default: Pick a directory from a dropdown or press `Esc` to use the home directory (`common` for Microsoft Account).

`aud:<domain|tenantId>`: Optional. Target Azure AD app id (aka client id) or domain the token should be created for (aka audience or resource). Default: Domain of the REST endpoint.
Copy link
Owner

@Huachao Huachao Jan 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could please also add the audience request in your aadToken.http?


* `{{$guid}}`: Add a RFC 4122 v4 UUID
* `{{$randomInt min max}}`: Returns a random integer between min (included) and max (excluded)
* `{{$timestamp}}`: Add UTC timestamp of now. You can even specify any date time based on current time in the format `{{$timestamp number option}}`, e.g., to represent 3 hours ago, simply `{{$timestamp -3 h}}`; to represent the day after tomorrow, simply `{{$timestamp 2 d}}`. The option string you can specify in timestamp are:
Expand Down Expand Up @@ -448,6 +450,17 @@ _**NOTE:** REST Client uses an in-memory token cache that clears when Visual Stu

_**NOTE:** `new` can be used with any other options, as long as it's specified first. Order is important for all options._

Specify an explicit Azure AD app (aka audience or resource):

```http
GET https://fabrikam.com/api/foo
Authorization: {{$aadToken aud:000000000000-0000-0000-0000-00000000}}
```

_**NOTE:** Audience (`aud`) must be an allowed value by the target API you are calling. Usually, this is a URL ending in a slash (/), but may also be an app/client id or other value. Contact the app owner to determine valid options._

_**NOTE:** Audience (`aud`) can be used with any other options, as long as it's specified last. Order is important for all options._

Implicit cloud selection (via REST endpoint TLD):

```http
Expand Down
11 changes: 6 additions & 5 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ export const AzureActiveDirectoryForceNewOption = "new";
export const AzureActiveDirectoryDefaultTenantId = "common";
export const AzureActiveDirectoryDefaultDisplayName = "Default Directory";
export const AzureClouds = {
ppe: {
aad: "https://login.windows-ppe.net/", // for testing purposes only
arm: "https://api-dogfood.resources.windows-int.net/",
armAudience: "https://management.azure.com/",
},
// default cloud must be first
public: {
aad: "https://login.microsoftonline.com/",
arm: "https://management.azure.com/",
Expand All @@ -58,6 +54,11 @@ export const AzureClouds = {
aad: "https://login.microsoftonline.us/",
arm: "https://management.usgovcloudapi.net/",
},
ppe: {
aad: "https://login.windows-ppe.net/", // for testing purposes only
arm: "https://api-dogfood.resources.windows-int.net/",
armAudience: "https://management.azure.com/",
},
};

export const CommentIdentifiersRegex: RegExp = /^\s*(#|\/{2})/;
Expand Down
5 changes: 3 additions & 2 deletions src/variableProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import * as moment from "moment";
const copyPaste = require('copy-paste');
const uuid = require('node-uuid');

const aadRegexPattern = `\\{\\{\\s*\\${Constants.AzureActiveDirectoryVariableName}(\\s+(${Constants.AzureActiveDirectoryForceNewOption}))?(\\s+(ppe|public|cn|de|us))?(\\s+([^\\.]+\\.[^\\}\\s]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))?\\s*\\}\\}`;
const aadRegexPattern = `\\{\\{\\s*\\${Constants.AzureActiveDirectoryVariableName}(\\s+(${Constants.AzureActiveDirectoryForceNewOption}))?(\\s+(ppe|public|cn|de|us))?(\\s+([^\\.]+\\.[^\\}\\s]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))?(\\s+aud:([^\\.]+\\.[^\\}\\s]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))?\\s*\\}\\}`;
const aadTokenCache = {};

export class VariableProcessor {
Expand Down Expand Up @@ -125,14 +125,15 @@ export class VariableProcessor {
cloud = targetApp.substring(targetApp.lastIndexOf(".") + 1, targetApp.length - 1);
}

// parse input options -- [new] [public|cn|de|us|ppe] [<domain|tenantId>]
// parse input options -- [new] [public|cn|de|us|ppe] [<domain|tenantId>] [aud:<domain|tenantId>]
let tenantId = Constants.AzureActiveDirectoryDefaultTenantId;
let forceNewToken = false;
const groups = new RegExp(aadRegexPattern).exec(url);
if (groups) {
forceNewToken = groups[2] === Constants.AzureActiveDirectoryForceNewOption;
cloud = groups[4] || cloud;
tenantId = groups[6] || tenantId;
targetApp = groups[8] || targetApp;
}

// verify cloud (default to public)
Expand Down
4 changes: 4 additions & 0 deletions test/aadToken.http
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,8 @@ Authorization: {{$aadToken us}}
// Explicit cloud selection -- ppe
GET {{arm-ppe}}/subscriptions?api-version=2017-08-01
Authorization: {{$aadToken ppe}}
###
// Explicit audience selection
GET {{graph}}/me?api-version=1.6
Authorization: {{$aadToken microsoft.com aud:https://management.core.windows.net/}}
###