microsoftgraph / aspnetcore-connect-sample

[ARCHIVED] This ASP.NET Core MVC sample shows how to connect to Microsoft Graph using delegated permissions and the Azure AD v2.0 (MSAL) endpoint.
MIT License
123 stars 96 forks source link

Unable to get access token #54

Closed deepika537 closed 4 years ago

deepika537 commented 4 years ago

Hello,

I downloaded the aspnetcore-connect-sample and I was successfully connected to Azure active directory but I could not get access token to get user profile and photo. Below function returns "null".

var account = await _app.GetAccountAsync(userId);

Please find my application details.

  1. ASP.net core 3.0 mvc web application
  2. using Microsoft.Identity.Client (4.3.1)
  3. I am using visual studio in MAC

Please provide your suggestion to get the access token.

mark-szabo commented 4 years ago

Hi @deepika537, that's absolutely fine that this line returns null. It means there is no valid token cached in the TokenCache (eg. you are trying to authenticate after you restarted the application).

This line should get you the token from AD: https://github.com/microsoftgraph/aspnetcore-connect-sample/blob/8870a81e985825495ddd6078127d1849715e41b6/MicrosoftGraphAspNetCoreConnectSample/Helpers/GraphAuthProvider.cs#L69

deepika537 commented 4 years ago

Thank you for your quick reply.

The below function also returns "null" because we are passing "account" as a parameter which is null.

var result = await _app.AcquireTokenSilent(_scopes, account).ExecuteAsync();

mark-szabo commented 4 years ago

Sorry, wrong line linked - my bad.

https://github.com/microsoftgraph/aspnetcore-connect-sample/blob/8870a81e985825495ddd6078127d1849715e41b6/MicrosoftGraphAspNetCoreConnectSample/Helpers/GraphAuthProvider.cs#L69

It will be called after the user authentication against AAD is successful:

https://github.com/microsoftgraph/aspnetcore-connect-sample/blob/8870a81e985825495ddd6078127d1849715e41b6/MicrosoftGraphAspNetCoreConnectSample/Extensions/AzureAdAuthenticationBuilderExtensions.cs#L83

deepika537 commented 4 years ago

My application got stuck in the function GetUserAccessTokenAsync() and it never entered the function GetUserAccessTokenByAuthorizationCode() because we call GetUserAccessTokenAsync() function from GraphSDKHelper.cs file at line 33.

Please find my code in GraphSDKHelper.cs file

// Get an authenticated Microsoft Graph Service client. public GraphServiceClient GetAuthenticatedClient(ClaimsIdentity userIdentity) { _graphClient = new GraphServiceClient(new DelegateAuthenticationProvider( async requestMessage => { // Get user's id for token cache. //userIdentity.FindFirst(ClaimTypes.NameIdentifier).Value; var identifier = userIdentity.FindFirst(Startup.ObjectIdentifierType)?.Value + "." + userIdentity.FindFirst(Startup.TenantIdType)?.Value;

                // Passing tenant ID to the sample auth provider to use as a cache key
                var accessToken = await _authProvider.GetUserAccessTokenAsync(identifier);

                // Append the access token to the request
                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

                // This header identifies the sample in the Microsoft Graph service. If extracting this code for your project please remove.
                requestMessage.Headers.Add("SampleID", "aspnetcore-connect-sample");
            }));

        return _graphClient;
    }

GraphAuthprovider.cs

public async Task GetUserAccessTokenAsync(string userId) { var account = await _app.GetAccountAsync(userId); if (account == null) throw new ServiceException(new Error { Code = "TokenNotFound", Message = "User not found in token cache. Maybe the server was restarted." });

        try
        {
            var result = await _app.AcquireTokenSilent(_scopes, account).ExecuteAsync();
            return result.AccessToken;
        }

        // Unable to retrieve the access token silently.
        catch (Exception)
        {
            throw new ServiceException(new Error
            {
                Code = GraphErrorCode.AuthenticationFailure.ToString(),
                Message = "Caller needs to authenticate. Unable to retrieve the access token silently."
            });
        }
    }

Whats wrong with my code?

mark-szabo commented 4 years ago

https://github.com/microsoftgraph/aspnetcore-connect-sample/blob/8870a81e985825495ddd6078127d1849715e41b6/MicrosoftGraphAspNetCoreConnectSample/Extensions/AzureAdAuthenticationBuilderExtensions.cs#L83

GetUserAccessTokenAsync() won't work for the first time, because it checks the existence of a token in the token cache and if it does not found anything, throws an error.

GetUserAccessTokenAsync() should not be called before authenticating the user first. You can see this here:

https://github.com/microsoftgraph/aspnetcore-connect-sample/blob/8870a81e985825495ddd6078127d1849715e41b6/MicrosoftGraphAspNetCoreConnectSample/Controllers/HomeController.cs#L34-L46

deepika537 commented 4 years ago

In My application, After clicking on login button, the value of "User.Identity.IsAuthenticated" is true and it entered in to the if loop and called the function (_graphSdkHelper.GetAuthenticatedClient((ClaimsIdentity)User.Identity); ) and the function throws an error.

After few secs final results says that we could not signIn, Please try again. I only replaced below line with email = email ?? User.Identity.Name;

Old Code: email = email ?? User.FindFirst("preferred_username")?.Value;

New Code: email = email ?? User.FindFirst("preferred_username")?.Value;

deepika537 commented 4 years ago

New code: email = email ?? User.Identity.Name

mark-szabo commented 4 years ago

Wait a sec. You are telling that you click the login button and you are not redirected to AD and authenticated correctly, but User.Identity.IsAuthenticated is true?

deepika537 commented 4 years ago

I entered my credentials and clicked on login button. After successful login I should be able to see my profile and photo instead of that it gave me an error because the applications do not have access token to get my details.

While debugging I came to know that the value of "User.Identity.IsAuthenticated" is true but the value of var account = await _app.GetAccountAsync(userId); is null.

I was successfully authenticated with AAD (because I can see home page without my profile data) but I could not connect to Microsoft Graph.

Please look at the screenshot below.

Screen Shot 2019-11-27 at 3 45 11 PM

deepika537 commented 4 years ago

I can see home page without profile details if I use below line in HomeController.cs

email = email ?? User.FindFirst("preferred_username")?.Value;

But If I replace the above line with below line then I can not see home page instead I see below page.

email = email ?? User.Identity.Name

Screen Shot 2019-11-27 at 3 59 09 PM

deepika537 commented 4 years ago

Hello,

Did you understand my problem?

Can you help me?

mark-szabo commented 4 years ago

Have you tried opening it in an incognito window? Maybe something with the cookies is corrupted.