aspnet/AspNetKatana

Microsoft.Owin.Security.MicrosoftAccount seems to return unverified email

Opened this issue · 2 comments

We have been using Microsoft.Owin.Security.MicrosoftAccount 4.2.2 for performing Microsoft login. The Email property from external login info was used to identify the user, but it seems like it returns back unverified email, which should not be used to identify user.

According to this article we are supposed to migrate away from using email claims for user identifications, but we are unable to get any of the remediation steps listed by Microsoft to work.
Setting the authentication behavior removeUnverifiedEmailClaim to true using graph API, doesn't work and still returns unverified email.
Further it seems like we can return an optional claim xms_edov to determine verification status but we were unable to get this claim returned in the id token as well.

if we make direct requests to grab the token on the v2 authorize and token end points the added optional claims seems to be returned fine. But using the middleware those claims are not getting returned.

What is the suggested step to make sure we don't get unverified email back using Microsoft Authentication?

I'm not sure why setting removeUnverifiedEmailClaim to true using the graph API isn't working for you. That seems unrelated to your usage of Microsoft.Owin.Security.MicrosoftAccount. You might have better luck asking about this over at https://github.com/microsoftgraph/msgraph-sdk-dotnet

if we make direct requests to grab the token on the v2 authorize and token end points the added optional claims seems to be returned fine. But using the middleware those claims are not getting returned.

Microsoft.Owin.Security.MicrosoftAccount uses the v2 authorize and token endpoints, but it doesn't map everything possible from the MicrosoftAccountAuthenticationOptions.UserInformationEndpoint (https://graph.microsoft.com/v1.0/me by default).

Fortunately, if you have an eagle eye, you'll notice the MicrosoftAccountAuthenticationHandler calls into a user-defined MicrosoftAccountAuthenticationOptions.Provider.OnAuthenticated callback where you can customize the ClaimsPrincipal with information from the MicrosoftAccountAuthenticatedContext.User JObject returned from the UserInformationEndpoint.

https://stackoverflow.com/a/22325623/719967 shows an example of how to do that. It's an async callback, and you have the MicrosoftAccountAuthenticatedContext.AccessToken at that point, so you're free to manually make whatever additional "direct requests" you've found that successfully return the added optional claims.

What is the suggested step to make sure we don't get unverified email back using Microsoft Authentication?

We generally suggest using something other than email like ClaimTypes.NameIdentifier for user identification. But if you want to check if the email provided is verified, your best bet is probably to check in the OnAuthenticated callback.

@halter73 Thankyou for your response. We made authentication requests to v2 authorize and token endpoints manually with openid profile email scopes and found the token endpoint returns both access_token and id_token. The id_token seems to honor all the requests. Although access_token is also a jwt, it didn't had any optional claims we asked for. With the id_token, We found that the optional claims were included and the authentication behavior - removeUnverifiedEmailClaim that was set using the graph API was working as well.
Looking at the code we figured MicrosoftAccount middleware doesn't even read the id_token. It uses user info endpoint to obtain the email of the account, and doesn't even expose the id_token on the OnAuthenticated callback, so there is no way to read the sent claims. We have opted to use OpenIdConnect middleware where we can read the claims from id_token and create new claims based on verified email.
While OpenIdConnect middleware serves the purpose, I am wondering if the MicrosoftAccount middleware can be updated to provide a way for users to read the id_token. The exposure of email that is unverified seems to make this package vulnerable.