Skip to content

Commit f9a1606

Browse files
committed
updates to node.js clientruntime (#1070)
* inital commit * minor update * some more updates * UserTokenCredentials use the token cache to retrieve tokens * updates to node.js clientruntime * update readme
1 parent 3cb1bec commit f9a1606

File tree

10 files changed

+260
-92
lines changed

10 files changed

+260
-92
lines changed

AutoRest/Generators/NodeJS/Azure.NodeJS/AzureNodeJSCodeGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Microsoft.Rest.Generator.Azure.NodeJS
1818
{
1919
public class AzureNodeJSCodeGenerator : NodeJSCodeGenerator
2020
{
21-
private const string ClientRuntimePackage = "ms-rest-azure version 1.14.0";
21+
private const string ClientRuntimePackage = "ms-rest-azure version 1.14.2";
2222

2323
// List of models with paging extensions.
2424
private IList<PageTemplateModel> pageModels;

AutoRest/Generators/NodeJS/NodeJS/NodeJSCodeGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace Microsoft.Rest.Generator.NodeJS
1616
{
1717
public class NodeJSCodeGenerator : CodeGenerator
1818
{
19-
private const string ClientRuntimePackage = "ms-rest version 1.14.0";
19+
private const string ClientRuntimePackage = "ms-rest version 1.14.2";
2020

2121
public NodeJsCodeNamer Namer { get; private set; }
2222

ClientRuntimes/NodeJS/ms-rest-azure/README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,18 @@ Otherwise it is better to use the above mechanism (interactive login).
4545
});
4646
```
4747

48-
### ServicePrincipal authentication
48+
#### Login with service principal name and secret
4949
```javascript
50-
var credentials = new msRestAzure.ApplicationTokenCredentials('your-client-id', 'your-domain', 'your-secret');
50+
var someAzureServiceClient = require('azure-arm-someService');
51+
msRestAzure.loginWithServicePrincipalSecret(clientId, secret, domain, function(err, credentials) {
52+
var client = new someAzureServiceClient(credentials, 'your-subscriptionId');
53+
client.someOperationGroup.method(param1, param2, function(err, result) {
54+
if (err) console.log(err);
55+
console.log(result);
56+
});
57+
});
5158
```
59+
5260
### Non-Interactive Authentication
5361
If you need to create an automation account for non interactive or scripting scenarios then please take a look at the documentation over [here](https://github.com/Azure/azure-sdk-for-node/blob/master/Documentation/Authentication.md).
5462

ClientRuntimes/NodeJS/ms-rest-azure/lib/credentials/applicationTokenCredentials.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,39 @@ function ApplicationTokenCredentials(clientId, domain, secret, options) {
6060
this.context = new adal.AuthenticationContext(authorityUrl, this.environment.validateAuthority, this.tokenCache);
6161
}
6262

63+
function _retrieveTokenFromCache (callback) {
64+
//For service principal userId and clientId are the same thing. Since the token has _clientId property we shall
65+
//retrieve token using it.
66+
this.context.acquireToken(this.environment.activeDirectoryResourceId, null, this.clientId, function (err, result) {
67+
if (err) return callback(err);
68+
return callback(null, result);
69+
});
70+
}
71+
72+
/**
73+
* Tries to get the token from cache initially. If that is unsuccessfull then it tries to get the token from ADAL.
74+
* @param {function} callback The callback in the form (err, result)
75+
* @return {function} callback
76+
* {Error} [err] The error if any
77+
* {object} [tokenResponse] The tokenResponse (tokenType and accessToken are the two important properties).
78+
*/
79+
ApplicationTokenCredentials.prototype.getToken = function (callback) {
80+
var self = this;
81+
_retrieveTokenFromCache.call(this, function (err, result) {
82+
if (err) {
83+
//Some error occured in retrieving the token from cache. May be the cache was empty or the access token expired. Let's try again.
84+
self.context.acquireTokenWithClientCredentials(self.environment.activeDirectoryResourceId, self.clientId, self.secret, function (err, tokenResponse) {
85+
if (err) {
86+
return callback(new Error('Failed to acquire token for application with the provided secret. \n' + err));
87+
}
88+
return callback(null, tokenResponse);
89+
});
90+
} else {
91+
return callback(null, result);
92+
}
93+
});
94+
};
95+
6396
/**
6497
* Signs a request with the Authentication header.
6598
*
@@ -68,15 +101,11 @@ function ApplicationTokenCredentials(clientId, domain, secret, options) {
68101
* @return {undefined}
69102
*/
70103
ApplicationTokenCredentials.prototype.signRequest = function (webResource, callback) {
71-
var self = this;
72-
self.context.acquireTokenWithClientCredentials(self.environment.activeDirectoryResourceId, self.clientId, self.secret, function (err, result) {
73-
if (err) {
74-
return callback(new Error('Failed to acquire token for application. \n' + err));
75-
}
76-
104+
this.getToken(function (err, result) {
105+
if (err) return callback(err);
77106
webResource.headers[Constants.HeaderConstants.AUTHORIZATION] =
78-
util.format('%s %s', self.authorizationScheme, result.accessToken);
79-
callback(null);
107+
util.format('%s %s', result.tokenType, result.accessToken);
108+
return callback(null);
80109
});
81110
};
82111

ClientRuntimes/NodeJS/ms-rest-azure/lib/credentials/userTokenCredentials.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,35 @@ function UserTokenCredentials(clientId, domain, username, password, options) {
6767
this.context = new adal.AuthenticationContext(authorityUrl, this.environment.validateAuthority, this.tokenCache);
6868
}
6969

70-
UserTokenCredentials.prototype.retrieveTokenFromCache = function (callback) {
71-
var self = this;
72-
self.context.acquireToken(self.environment.activeDirectoryResourceId, self.username, self.clientId, function (err, result) {
70+
function _retrieveTokenFromCache(callback) {
71+
this.context.acquireToken(this.environment.activeDirectoryResourceId, this.username, this.clientId, function (err, result) {
7372
if (err) return callback(err);
74-
return callback(null, result.tokenType, result.accessToken);
73+
return callback(null, result);
74+
});
75+
}
76+
77+
/**
78+
* Tries to get the token from cache initially. If that is unsuccessfull then it tries to get the token from ADAL.
79+
* @param {function} callback The callback in the form (err, result)
80+
* @return {function} callback
81+
* {Error} [err] The error if any
82+
* {object} [tokenResponse] The tokenResponse (tokenType and accessToken are the two important properties).
83+
*/
84+
UserTokenCredentials.prototype.getToken = function (callback) {
85+
var self = this;
86+
_retrieveTokenFromCache.call(this, function (err, result) {
87+
if (err) {
88+
//Some error occured in retrieving the token from cache. May be the cache was empty. Let's try again.
89+
self.context.acquireTokenWithUsernamePassword(self.environment.activeDirectoryResourceId, self.username,
90+
self.password, self.clientId, function (err, tokenResponse) {
91+
if (err) {
92+
return callback(new Error('Failed to acquire token for the user. \n' + err));
93+
}
94+
return callback(null, tokenResponse);
95+
});
96+
} else {
97+
return callback(null, result);
98+
}
7599
});
76100
};
77101

@@ -83,9 +107,10 @@ UserTokenCredentials.prototype.retrieveTokenFromCache = function (callback) {
83107
* @return {undefined}
84108
*/
85109
UserTokenCredentials.prototype.signRequest = function (webResource, callback) {
86-
return this.retrieveTokenFromCache(function(err, scheme, token) {
110+
this.getToken(function (err, result) {
87111
if (err) return callback(err);
88-
webResource.headers[Constants.HeaderConstants.AUTHORIZATION] = util.format('%s %s', scheme, token);
112+
webResource.headers[Constants.HeaderConstants.AUTHORIZATION] =
113+
util.format('%s %s', result.tokenType, result.accessToken);
89114
return callback(null);
90115
});
91116
};

ClientRuntimes/NodeJS/ms-rest-azure/lib/index.d.ts

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,40 @@ export interface AzureTokenCredentialsOptions {
150150
*/
151151
authorizationScheme?: string;
152152

153-
// TODO: What type should this really have? How is it used?
154153
/**
155-
* The token cache. Default value is null.
154+
* The token cache. Default value is MemoryCache from adal.
156155
*/
157156
tokenCache?: any;
158157
}
159158

159+
export interface LoginWithUsernamePasswordOptions extends AzureTokenCredentialsOptions {
160+
/**
161+
* The domain or tenant id containing this application. Default value is 'common'.
162+
*/
163+
domain?: string;
164+
165+
/**
166+
* The active directory application client id.
167+
* See {@link https://azure.microsoft.com/en-us/documentation/articles/active-directory-devquickstarts-dotnet/ Active Directory Quickstart for .Net}
168+
* for an example.
169+
*/
170+
clientId?: string
171+
}
172+
173+
export interface DeviceTokenCredentialsOptions extends LoginWithUsernamePasswordOptions {
174+
/**
175+
* The user name for account in the form: '[email protected]'. Default value is '[email protected]'.
176+
*/
177+
username?: string;
178+
}
179+
180+
export interface InteractiveLoginOptions extends DeviceTokenCredentialsOptions {
181+
/**
182+
* The language code specifying how the message should be localized to. Default value 'en-us'.
183+
*/
184+
language?: string;
185+
}
186+
160187
export class ApplicationTokenCredentials extends msRest.ServiceClientCredentials {
161188
/**
162189
* Creates a new ApplicationTokenCredentials object.
@@ -179,12 +206,79 @@ export class UserTokenCredentials extends msRest.ServiceClientCredentials {
179206
* @param {string} domain The domain or tenant id containing this application.
180207
* @param {string} username The user name for the Organization Id account.
181208
* @param {string} password The password for the Organization Id account.
182-
* @param {string} clientRedirectUri The Uri where the user will be redirected after authenticating with AD.
183209
* @param {AzureTokenCredentialsOptions} options Object representing optional parameters.
184210
*/
185-
constructor(clientId: string, domain: string, username: string, password: string, clientRedirectUri: string, options?: AzureTokenCredentialsOptions);
211+
constructor(clientId: string, domain: string, username: string, password: string, options?: AzureTokenCredentialsOptions);
212+
}
213+
214+
export class DeviceTokenCredentials extends msRest.ServiceClientCredentials {
215+
/**
216+
* Creates a new DeviceTokenCredentials object.
217+
* @param {DeviceTokenCredentialsOptions} options Object representing optional parameters.
218+
*/
219+
constructor(options?: DeviceTokenCredentialsOptions);
186220
}
187221

188222
// TODO: WHAT SHOULD WE EXPOSE HERE?
189223
export class BaseResource {
190224
}
225+
226+
/**
227+
* Provides a url and code that needs to be copy and pasted in a browser and authenticated over there. If successful, the user will get a
228+
* DeviceTokenCredentials object
229+
*
230+
* @param {InteractiveLoginOptions} [options] The parameter options.
231+
*
232+
* @param {function} callback
233+
*
234+
* @returns {function} callback(err, credentials)
235+
*
236+
* {Error} [err] - The Error object if an error occurred, null otherwise.
237+
*
238+
* {DeviceTokenCredentials} [credentials] - The DeviceTokenCredentials object
239+
*/
240+
export function interactiveLogin (options?: InteractiveLoginOptions, callback);
241+
242+
/**
243+
* Provides a UserTokenCredentials object. This method is applicable only for organizational ids that are not 2FA enabled.
244+
* Otherwise please use interactive login.
245+
*
246+
* @param {string} username The user name for the Organization Id account.
247+
*
248+
* @param {string} password The password for the Organization Id account.
249+
*
250+
* @param {LoginWithUsernamePasswordOptions} [options] The parameter options.
251+
*
252+
* @param {function} callback
253+
*
254+
* @returns {function} callback(err, credentials)
255+
*
256+
* {Error} [err] - The Error object if an error occurred, null otherwise.
257+
*
258+
* {UserTokenCredentials} [credentials] - The UserTokenCredentials object
259+
*/
260+
export function loginWithUsernamePassword (username: string, password: string, options?: LoginWithUsernamePasswordOptions, callback);
261+
262+
263+
/**
264+
* Provides an ApplicationTokenCredentials object.
265+
*
266+
* @param {string} clientId The active directory application client id also known as the SPN (ServicePrincipal Name).
267+
* See {@link https://azure.microsoft.com/en-us/documentation/articles/active-directory-devquickstarts-dotnet/ Active Directory Quickstart for .Net}
268+
* for an example.
269+
*
270+
* @param {string} secret The application secret for the service principal.
271+
*
272+
* @param {string} domain The domain or tenant id containing this application.
273+
*
274+
* @param {AzureTokenCredentialsOptions} [options] The parameter options.
275+
*
276+
* @param {function} callback
277+
*
278+
* @returns {function} callback(err, credentials)
279+
*
280+
* {Error} [err] - The Error object if an error occurred, null otherwise.
281+
*
282+
* {ApplicationTokenCredentials} [credentials] - The ApplicationTokenCredentials object
283+
*/
284+
export function loginWithServicePrincipalSecret (clientId: string, secret: string, domain: string, options?: AzureTokenCredentialsOptions, callback);

0 commit comments

Comments
 (0)