Goals: We would like to support the authorization code flow with PKCE for Single Page Applications in browser environments.
Milestones:
This is the first version of the library available for private preview. We do NOT recommend anyone use this in their production apps - this is only for testing if anyone is interested. Please feel free to reach out if you run into any issues or have any feedback for improving what we have released. We will have a more detailed announcement and release notes for this when we reach the beta stage.
In the coming weeks, we will be updating this package actively based on internal testing and external feedback.
[x] Beta Release
Coming soon!
[ ] Main Release
Work has started for this item.
Is there an ETA for this landing?
@garrettm It is inside October 2019 milestone, so we may expect to try it soon 馃
We are working on it in October! @garethj-msft @sergey-tihon however it will likely take us through the rest of the quarter to finish. Expect to be able to use it in production early 2020.
Alright, thanks. Might there be a less stable version we can use beforehand? Or is there an alternative library I could use for this until msal is ready? https://github.com/AzureAD/azure-activedirectory-library-for-js ?
This will be awesome to be able to use SPA/PWA apps with Microsoft Azure AD and Authorization Code Flow with PKCE, is this going to enable the possibility?
Yes. @pkanher617 to add more details.
@garrettm @sergey-tihon We are currently developing this, hope to have the beta version ready by Christmas.
@garrettm msal for implicit flow is available and currently at v1.1.3, so you can use that instead of the ADAL library for now.
@Romiko yes, we would like to support the use cases for SPA/PWA apps using Auth Code w/ PKCE.
@pkanher617 sorry, I'm not sure what you mean, isn't this repo/issue about getting an Auth Code through msal? How can I use msal for this when it's still not ready? Am I misunderstanding something?
@garretm sorry I may have misunderstood what it was that you were looking for - I saw a link to the ADAL.js repo and assumed you were simply looking for an upgraded version of what is supported in ADAL today.
You aren't misunderstanding anything, this issue will track making the Authorization Code Flow available in MSAL.
@pkanher617 I see there's a PR for this. Thanks! Is it still on track for a beta this month?
@garrettm this is still planned to be code complete by the end of this month, however there are a few things that this depends on from the server / portal side that will not complete their parts until early 2020.
@DarylThayil got it, thanks for the update!
Any news?
We are very close to finishing the implementation, @pkanher617 will be updating the details soon. We will be announcing an ~alpha version first in couple weeks for private consumption and we plan to incrementally take feedback to build up to a major release.
How do we get on that private consumption list :)
How do we get on that private consumption list :)
I'd also like to be on the private consumption list!
Please watch out this space, we will make the announcement. Thanks for the interest and we count on customers like you to provide us active feedback.
UPDATE: We are planning on releasing an alpha this week for the Authorization Code Flow library. I will link a doc here for instructions on how to download and use the alpha in an npm project. Checking to see if we have a possibility for a CDN solution for the alpha as well.
UPDATE: We have released the alpha for Auth Code Flow as a new package in npm. Please download it here.
@pkanher617 thank you! Do you have a timeline for when when this will be out of alpha and stable for shipping apps?
@garrettm We are waiting on a few other teams to finish features, namely some server side features to support CORS requests and refresh tokens for SPAs. We are hoping to have the stable full release available sometime in the March-April timeframe.
@pkanher617 got it, thanks. I thought the auth code would allow a SPA to get a refresh token (on the frontend or backend). Is that not supported yet in this alpha?
@pkanher617 bug to report, I think?
In SessionStorage, msal.[uuid].interaction.status got stuck on interaction_in_progress and now .loginPopup(params) fails every time, even between refreshes.
@garrettm Thanks! Could you please file an issue in this repo with repro steps?
I thought the auth code would allow a SPA to get a refresh token (on the frontend or backend). Is that not supported yet in this alpha?
Yes this will be supported in the alpha, but as I said above this currently does not work in browsers that have CORS protection. Disable this security for the alpha to test, but it is not production ready. The service team will let us know when we are able to implement this for all browsers.
Is there any planned release date for this feature?
I just tried the alpha release in chrome browser with cors-setting disabled and I still could not find the auth code in its response and I don't see any clear details like how to fetch the auth-code in this NPM library README file. Could anyone say how to get the auth code by using this package? I was playing around with "samples/VanillaJSTestApp"
@develm We are planning to release this sometime in March. The beta version of the library should be out later this month as well. No exact timelines, we are waiting on other teams and services to roll out features. Please come back to this issue for updates.
@gitvishnu The MSAL library does not give back an auth code- it retrieves tokens using the auth code flow. If you have a use case for only receiving an authorization code, I am happy to discuss it here, but for now this library will retrieve tokens using an authorization code without giving this code back to the user.
@pkanher617
Thank your quick response.
Unfortunately I also need the auth code from this library.
I have multiple unsecure client applications (web and mobile) that need to acquire authorization code using only clientId. Authorization code generated this way can not be exchanged without the clientSecret.
The code is then passed to a secure api that has the appropriate clientSecret and can exchange auth code for user information.
This way sensitive information never passes trough client code ie. javascript that is susceptible to attacks. PKCE flow just makes no sense as we already support other providers with this flow.
Will there be no way to just acquire the auth code without PKCE?
@pkanher617 Sorry I was expecting that it will return the auth code in its response or as a query param when it is getting redirected into the redirect uri. so is there any option to get the auth code from the MSAL js?
@pkanher617 Any news on CDN solution for the alpha?
@MXuWu We are running into a few issues with our CDN provider, we are working to restore the service moving forward, but there is expected to be CDN available for versions going forward. i will update here when it is available.
@pkanher617 Will the auth code flow remove the limitation of returning no more than 6 groups in an access token that the current implicit flow has?
Is this still on track for a March release? We're keen to move away from the implicit flow when we can.
@pkanher617 Hi, are there any news regarding the CORS support? Is there an issue where we can track the progress of the server-side team?
We need the CORS support for the code grant flow because the implicit grant flow does not provide the 'groups' claim.
@JamesBream I'm unfamiliar with that particular issue, but I do know of the issue with tokens being truncated in the url hash for implicit flow. We will no longer have restrictions on size limits for tokens since these are coming back in http responses. If your issue is related to something other than token size, I will have to understand a little more about the use case.
It is still on track for an end of March release barring any delays from the portal UI.
I am also very keen on this change. (Any preview doco would be appreciated). I advocated for using auth code flow in our server side applications, and I can't in good conscience launch an app using implicit in 2020. Thanks for your efforts!
@pkanher617 I'm testing out the alpha and I'm seeing issues using loginRedirect when specifying multiple scopes:
msalInstance.loginRedirect({
scopes: [
'openid',
'profile',
'email',
'https://graph.microsoft.com/User.ReadBasic.All',
'https://microsoft.onmicrosoft.com/my.api/user_impersonation',
],
});
Once the user completes the login and is redirected back to my app, MSAL requests an access token and gets a 400 response with the error AADSTS28000: Provided value for the input parameter scope is not valid because it contains more than one resource. Scope openid profile email https://graph.microsoft.com/user.readbasic.all https://microsoft.onmicrosoft.com/my.api/user_impersonation offline_access is not valid.
I'm wondering, why is MSAL even making a request for access tokens at this point? I'm not calling any of the acquireToken methods yet.
The reason I include these scopes is to get pre-consent on login (docs), not to get access tokens. I will get access tokens later, per resource, via acquireTokenSilent.
However, if I don't include scopes in the login request, I see acquireTokenSilent fail with 'ClientAuthError: No tokens were found for the given scopes, and no authorization code was passed to acquireToken.
Is there a bug here? or how can I support getting access to tokens for multiple resources?
@pkanher617 any updates on ETA for this?
@deasems I stumbled through here with precisely the same error. If it's useful for anyone (@garrettm ?) the following workflow is functional for folks playing with this release:
.loginPopup() is requesting a token for all scopes in [ scopes ], which does seem like unexpected behavior (Unexpected No. 1). The flow is here: loginPopup > popupTokenHelper > handleCodeResponse > acquireToken.
We can take advantage of this during login by grabbing a token for whichever scope/resource is needed first (management, in this example). Furthermore, extraScopesToConsent lets us go ahead and have the user approve everything up front (on first authentication):
const scopes = {
management: 'https://management.azure.com/user_impersonation',
batch: 'https://batch.core.windows.net//user_impersonation',
blob: 'https://*.dfs.core.windows.net/user_impersonation'
}
let tokenResponse = await msal.loginPopup({
scopes: [ scopes.management ],
extraScopesToConsent: Object.values(scopes) // This is a nice touch.
})
Then we can use said token for whatever task:
const subscriptions = await get(endpoints.subscriptions, tokenResponse.accessToken)
Once we're ready for the next token, there is a difference between the acquireTokenSilent and acquireTokenPopup methods. Easiest seen in their typing:
acquireTokenPopup(request: AuthenticationParameters): Promise<TokenResponse>;
// ^ same as the .loginPopup()
acquireTokenSilent(tokenRequest: TokenRenewParameters): Promise<TokenResponse>;
// ^ wholly different!
Interestingly, the following will succeed (despite the annoying popup flash -- the user doesn't
need to consent again, so the popup closes immediately):
tokenResponse = await msal.acquireTokenPopup({
scopes: [ scopes.batch ] // New scope for new token.
})
...but this will not...
tokenResponse = await msal.acquireTokenSilent({
scopes: [ scopes.batch ] // New scope for new token.
})
...which we can see by the error (and 401 on the GET):
The access token has been obtained from wrong audience or resource 'https://management.azure.com'.
Ah-ha! Unexpected Behavior No.2. Looks like the [ The Caching Mechanism ] has something
funky going on and is mixing up tokens/resources/audiences when we interleave requests to different resources/scopes.
Two apparent workarounds:
Use acquireTokenPopup. The user gets popup-flashed, but the token comes back clean.
Add forceRefresh to the acquireTokenSilent call. This makes an extra trip to the server
(assuming the token ever was cached correctly, locally), but the token comes back clean:
tokenResponse = await msal.acquireTokenSilent({
scopes: [ scopes.batch ],
forceRefresh: true // Demand a new token!
})
Tokens for everyone!
@pkanher617 sorry to bother you again, but are there any updates on when this might leave alpha?
Hi all, sorry for the delay on updating this.
We have released a beta version of the library here. There are more detailed docs available in the README of the repository folder.
@deasems You should be able to consent to multiple scopes in the login call. Could you try to use the beta version and see if you are still have the issue?
If you are having issue with this, please open a separate issue in Github. If you have, please link it here. I apologize if we haven't seen it yet. This may be an issue with the formatting of the scopes as well. Does this work in the msal package?
@pkanher617 I updated my app to the beta (thanks for the improved docs) and can still reproduce the issue. I've opened #1487
For all following this thread, please participate in our private preview next week! You will be able to test out enabling the auth code flow for SPAs in the azure portal. Fill out this form to be part of the preview: https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR_XA414hlD9MhfBiqanxI2JUOElQMk1LUjNBWDY4R0w3MFlPR0FIMkxMVC4u
@deasems @garrettm @samb-pd @markau @JamesBream @andreifloricel @MXuWu @gitvishnu @oliverjanik @develm @Romiko @sergey-tihon @xom-pschiess
@hamiltonha hello! Is this private preview to test out new B2C CORS and PKCE settings? To clarify, I used a fake client secret last week with PKCE and was able to retrieve an access token without CORS issues (using a 3rd party OAuth JS library). But today I'm not able to; and seeing your message from 7 days ago regarding a private preview of SPA support has my head spinning! Now I'm not sure if things worked last week.
@jake-brandt Hi Jake, unfortunately B2C support for this feature is not ready yet for the private preview, but will be coming shortly after. I'm not sure why it would have worked last week and not this week.
Thank you @hamiltonha - appreciate the confirmation!
Hi! I'm testing this functionality in my company and I'm finding that when requesting the token, Azure AD gives me the three of them (Id Token, Access Token and Refresh Token). I'm not very comfy with having refresh nor access tokens in the browser, does anybody know if there is a way of configuring Azure AD to not to return these kind of tokens to the client only in case it is a browser-based app?
@hamiltonha I'm a bit late to the preview party but still interested in testing this if you need further feedback 馃檪
@hamiltonha is the preview on for this week? I filled out the form, will I be getting an email or is it already ongoing?
@JamesBream please fill out this form to participate :) https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR_XA414hlD9MhfBiqanxI2JUOElQMk1LUjNBWDY4R0w3MFlPR0FIMkxMVC4u
@garrettm I'm just waiting for the preview portal link to be deployed, which could take a few days, then you will be hearing from me with more details if you filled out the form
@dedreira in the Azure portal you can uncheck the settings for id token and access token under implicit grant settings. However, yes this latest version of MSAL js uses the auth code flow which uses an authorization code to retrieve an access token and a refresh token. You can read more about OAuth latest recommendation to use the auth code flow with browser based apps: https://tools.ietf.org/html/draft-ietf-oauth-browser-based-apps-04#page-9
@hamiltonha thanks for the quick answer! I tried it and I'm afraid when using PKCE it doesn't matter if I uncheck the settings for access token under implicit grant settings...
I was reading this document https://tools.ietf.org/html/draft-ietf-oauth-browser-based-apps-06#section-8 that seems to be more recent and suggest this:
Authorization servers may choose whether or not to issue refresh
tokens to browser-based applications
I was just wondering if Azure AD Team was working on this, as it appears you have unlocking Auth Code with PKCE for browser-based apps recently.
Thanks again 馃槂
@dedreira I'm a bit confused by what you are asking here. This library is meant to implement the authorization code flow for SPAs and allow you to retrieve access tokens in the front end. We also have an implicit flow library here that you can use to only retrieve id_tokens.
To be clear, the refresh tokens used by MSAL.JS are limited-lifetime non-renewable refresh tokens (24 hours) which are used to silently renew the access or id tokens acquired without opening an iframe (instead using fetch or XHR to renew a token using a CORS-protected POST request to the token endpoint). This feature allows applications to partially work around limitations placed by features similar to Intelligent Tracking Prevention 2.0 that prevent silent token renewal in Safari and soon other modern browsers. If we choose to not distribute refresh tokens we no longer have a mechanism to perform this workaround.
We are also working on a Node.js library for server-side interactions, if that is something that would fit your use case better.
@pkanher617 sorry to hear that, I was thinking about the security of my SPAs .
I understand the possibilities that a silent token renew feature can bring to end-users, but the possibility of a token leak (as you'd know, it's impossible to keep secrets in browser-based apps) must be taken in account too.
IETF recommends against using the Implicit flow entirely in SPAs (as you can read here and gives some advices to configure the Authorization server to support PKCE for browser-based apps in a more "secure" way (https://tools.ietf.org/html/draft-ietf-oauth-browser-based-apps-06#section-8) . I was just asking if there will be a way to configure the authorization server to not to return refresh tokens , just in case someone wants to. I don't really think this is a nonsense.....
I realize that maybe this is not the place to request this kind of info because here you're developing a client library, but I thought that maybe you could redirect me to the correct forum.
@dedreira I think this is a good place to bring that up, thank you for posting here!
In general, tokens aren't secure in browser-based apps, and it is up to the developer to make sure they do their due-diligence in preventing these attacks. We are doing as much as we can from our side to make this secure, using limited-lifetimes and other mitigations.
Talking to the server team, v1 endpoints do not allow you to do this, but on v2 endpoints you can use these flows without a refresh token by omitting the offline_access scope. We currently add offline_access by default for all calls. I will do some investigating, but I may be able to add a configuration option which allows you to omit this scope on auth calls, that way you will only receive id_tokens and access tokens.
Be aware that there may be a performance tradeoff for this, please let me do some more investigation.
@pkanher617 thanks a lot for your research!
I've been trying the v2 endpoints without the offline_access scope and I'm still receiving the refresh token, this is the call I'm performing, just for your information:
Authorize Endpoint
https://login.microsoftonline.com/#my-tenant-id#/oauth2/v2.0/authorize?client_id=#my-spa-client-id#&redirect_uri=#my-spa-redirect-uri#&response_type=code&scope=openid%20profile%20email%20#a-web-api-custom-scope#&state=#state#&code_challenge=#code_challenge#&code_challenge_method=S256&response_mode=query
After this call, when I finish the authentication process and I call the token endpoint (v.2.0 also) I'm still getting the refresh token.
May be there's something I'm missing, but I don't get it...
@pkanher617 and @hamiltonha, do you know if we will be able to set up B2C to issue refresh tokens as a cookie while returning access tokens in the normal JSON response? In the past I've employed refresh tokens this way with a CSRF antiforgery token, rather than returning refresh tokens in the body. In the world of SPAs, many apps use quite a few 3rd party libraries which may have their own XSS or related vulnerabilities.
Hi,
I am trying the public preview (https://www.npmjs.com/package/@azure/msal-browser)
I am using acquireTokenPopup method to get the token. It works but I could see that the consent box was not showing.
Any idea about it?
Edited: the consent box appears for personal account only
@kylephp You should be able to change the settings for consent display options by going to the "API permissions" section of your app registration in the azure portal
@hamiltonha Thanks for replying but I could not find it in "API Permissions"
Hi @hamiltonha , just wondering do you know a rough ETA for B2C integration?
@luklew you should be able to use B2C now by manually editing your app manifest as instructed in the README of the browser package. The azure portal URI for SPAs will be deployed to B2C tenants around June 5-12th. please let me and @pkanher617 know if you have any issues using the browser package with a b2c app by editing the manifest
@hamiltonha I will do thanks! Does this work with angular msal 1.0.0?
@luklew as of now the Angular library still uses the implicit flow, we are looking to onboard that library to the auth code flow in the coming months.
@hamiltonha I've noticed I'm not getting all my Application Claims back from the B2C AD when I request a token. Is that expected at this time?
I have edited the manifest and changed the type to "spa", also enabled "public client" btw.
@luklew as of now the Angular library still uses the implicit flow, we are looking to onboard that library to the auth code flow in the coming months.
@hamiltonha any update on this? trying to get an idea when we can expect angular spa with pkce/auth code flow.
@hamiltonha I would also like to know about the plans for implementing this for the Angular wrapper. Any information would be highly appreciated.
@mblagdan @siva-srini - @jasonnutter is currently working on a sample angular app that uses MSAL.js 2.0 directly. We also will be discussing prioritizing onboarding the Angular wrapper to the MSAL.js 2.0 with auth code/pkce in the coming months now the library is GA.
Closing, as MSAL Browser is now GA. If you have further questions or concerns, please open a new issue, thanks!
Most helpful comment
For all following this thread, please participate in our private preview next week! You will be able to test out enabling the auth code flow for SPAs in the azure portal. Fill out this form to be part of the preview: https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR_XA414hlD9MhfBiqanxI2JUOElQMk1LUjNBWDY4R0w3MFlPR0FIMkxMVC4u
@deasems @garrettm @samb-pd @markau @JamesBream @andreifloricel @MXuWu @gitvishnu @oliverjanik @develm @Romiko @sergey-tihon @xom-pschiess