Make token credentials compatible with @azure/core-auth's TokenCredential#66
Make token credentials compatible with @azure/core-auth's TokenCredential#66daviwil wants to merge 12 commits intoAzure:masterfrom
Conversation
|
Worth noting that the CI build will fail because we haven't shipped |
80f4186 to
c9f02fc
Compare
|
PR Azure/azure-sdk-for-js#4367 restricts the |
lib/credentials/coreAuthHelpers.ts
Outdated
| export function prepareToken<T extends TokenResponseLike>( | ||
| token: T, | ||
| scopes: string | string[] | undefined): T | AccessToken { | ||
| if (scopes) { |
There was a problem hiding this comment.
What if scopes is an empty string ? This check will fail for that. If the intention is to check specifically for null or undefined then using the "double equal to" or "not with a single equal to" will be a good check as that will take care of null and undefined.
if (scopes != undefined)
There was a problem hiding this comment.
Thanks! It shouldn't be an empty string, but you never know what a user might do. I'll make the check stricter.
There was a problem hiding this comment.
On second thought, the idea is check for whether a parameter was passed to scopes, not to scrutinize whether the value of scopes is valid. I think in this case I'm only concerned about whether it's explicitly undefined since that's what the parameter would contain if nothing was passed.
BearerTokenAuthenticationPolicy in core-http will always pass a string or an array to the scopes parameter so I think it's pretty safe to only check for undefined since we don't actually use the real value of scopes in these forward-compatible implementations anyway.
package.json
Outdated
| "dependencies": { | ||
| "@azure/core-auth": "1.0.0-preview.1", | ||
| "@azure/ms-rest-azure-env": "^1.1.2", | ||
| "@azure/ms-rest-js": "^1.8.7", |
There was a problem hiding this comment.
Should this be replaced by @azure/core-http? By not moving to core-http do we risk having type conflicts for the customer in his/her application?
There was a problem hiding this comment.
Nah, we pulled the TokenCredential interface and related types into @azure/core-auth so that they can be reused in other places. @azure/core-http depends on @azure/core-auth in the unshipped code in master.
|
For safety, I would let this be a major version bump (3.0.0). It keeps a clear boundary between new stuff and the old stuff. Makes things easier for us to maintain. |
| return { | ||
| token: token.accessToken, | ||
| expiresOnTimestamp: | ||
| typeof token.expiresOn === "string" |
There was a problem hiding this comment.
This assumes that expiresOn exists on all the credential types in ms-rest-nodeauth.
Are we sure about this assumption?
There was a problem hiding this comment.
Good point, I can't find expiresOn being assigned anywhere in a few of the credential implementations. @amarzavery, do you remember how users are supposed to deal with token expiration in this library? I only see AzureCliCredentials implementing any kind of token refresh logic.
There was a problem hiding this comment.
adal-node has an in memory token cache. It gets a new token if it is about to get expired or gives the token from the token cache.
For AzureCliCredentials we are calling the cli to authenticate and give us the new token that will be valid for the next one hour. Cli knows how to refresh the token if it is using it internally. We can't be calling the Cli for every request, as that will terribly slow down the sdk (spawning a new process and asking the Cli for creds).
Thus we try to do the same thing that adal-python would do anyways (if we are within the token refresh window (last 5 mins before the token expiry) then ask the Cli for token, it will ask adal-python which will then get the new token that will be valid for the next one hour).
Thus we need to check the expiresOn property.
There was a problem hiding this comment.
I've loosened the expectation of an expiresOn property on the token and put a default expiration timestamp of an hour if one is not provided. What do you think?
lib/credentials/coreAuthHelpers.ts
Outdated
| @@ -0,0 +1,28 @@ | |||
| import { AccessToken } from "@azure/core-auth"; | |||
|
|
|||
| export interface TokenResponseLike { | |||
There was a problem hiding this comment.
Does this have to be exported? I don't see it being referenced anywhere other than this file
There was a problem hiding this comment.
Possibly not, I'll give it a shot.
There was a problem hiding this comment.
Looks like removing the export worked fine!
| return reject(tokenResponse); | ||
| } | ||
| return resolve(tokenResponse as TokenResponse); | ||
| return resolve(prepareToken(tokenResponse as TokenResponse, scopes)); |
There was a problem hiding this comment.
Nit: Where-ever applicable, please consider having a const for the prepared token instead of inlining the call to prepareToken in this manner. Having the call in a separate line would make it easier to add breakpoints when debugging
There was a problem hiding this comment.
Sounds good, I'll make that change.
| import { assert } from "chai"; | ||
| import { prepareToken } from "../../lib/credentials/coreAuthHelpers"; | ||
|
|
||
| describe("prepareToken", function() { |
There was a problem hiding this comment.
There are 2 test files for MSI creds at the moment.
Can we update the test cases in these files to include a call to getToken(scopes) to check that the returned value is of type AccessToken?
There was a problem hiding this comment.
I'll give it a shot
There was a problem hiding this comment.
Added a test in each MSI spec file to verify that an AccessToken is returned when a scope is passed to getToken. Is that sufficient?
Having creds from ms-rest-nodeauth be compatible with core-auth doesnt solve the problem that was being fixed in Azure/azure-sdk-for-js#4335 does it? Or are we expecting that a combination of the above and Azure/azure-sdk-for-js#4367, solves the issue in Azure/azure-sdk-for-js#4335 |
Yep, it's the combination of fixes that mostly solves the problem. Previously the problem was that After these new two PRs, we only ever use This does leave us with one problem, though: we don't have a reliable way to distinguish between a I'd be happy to hear if someone has an idea for how to get around this problem! |
|
Had a better idea on how to make |
| */ | ||
| public async getToken(): Promise<TokenResponse> { | ||
| public getToken(): Promise<TokenResponse>; | ||
| public getToken(scopes: string | string[], options?: GetTokenOptions): Promise<AccessToken>; |
There was a problem hiding this comment.
Why no async keywords for the overloads?
There was a problem hiding this comment.
Because the overload definitions are just typings and async is only really needed with a function body that uses await. That said, I'll add the keywords to minimize confusion.
There was a problem hiding this comment.
My confusion was because in a couple of places we did add the async keyword for the overloads, and in some places we didnt
| public getToken(): Promise<TokenResponse> { | ||
| public getToken(): Promise<TokenResponse>; | ||
| public getToken(scopes: string | string[], options?: GetTokenOptions): Promise<AccessToken>; | ||
| public async getToken(scopes?: string | string[]): Promise<TokenResponse | AccessToken> { |
There was a problem hiding this comment.
Missing async keywords on the overloads
Changelog.md
Outdated
| @@ -1,4 +1,9 @@ | |||
| # Changelog | |||
|
|
|||
| ## 3.0.0 - 2019/07/19 | |||
There was a problem hiding this comment.
Date would need an update
There was a problem hiding this comment.
I'll update it before merging
565a9fe to
10e63d5
Compare
Merge from master and update deps
|
This PR is no longer necessary as we've made |
This change makes
ms-rest-nodeauthtoken credential implementations compatible with@azure/core-auth'sTokenCredential, enabling them to be used with Track 2 SDK libraries. This is part of the resolution for Azure/azure-sdk-for-js#4108.I've verified these changes with
DeviceTokenCredentials,AzureCliCredentials, andApplicationTokenCredentialsusing a version of@azure/arm-resourcesthat does not acceptServiceClientCredentialsin itsServiceClientconstructor. I also removed the use ofsigningPolicyin@azure/core-authin my local build just to make sure these credentials are being used withBearerTokenAuthenticationPolicy.One implication of this change is that the fix we made to
isTokenCredentialin Azure/azure-sdk-for-js#4335 now has to be rolled back because all of these credentials now expose bothgetTokenandsignRequestdue to implementing bothServiceClientCredentialsandTokenCredential. I'll make a PR to@azure/core-httpif we decide we like this compatibility approach.Questions for Reviewers
prepareToken? Doesn't seem explicit enough to me so I'm open to ideas for a better name.