Search code examples
c#azuremicrosoft-graph-apimicrosoft-graph-sdksmsal

Why are PublicClientApplicationBuilder requires client(app) Secret?


My final goal is manage user's access token by refresh token. I need token from user.

So, I tried this logic.

var app = PublicClientApplicationBuilder.Create(clientId)
    .WithRedirectUri(redirectUri)
    .WithTenantId(tenantId)
    .Build();

var accounts = app.GetAccountsAsync().Result;
              
 var authResult = app.AcquireTokenInteractive(scopes)
 .ExecuteAsync().Result;
 var token = authResult.AccessToken

An error occurs in app.AcquireTokenInteractive(scopes) after logging in with a Microsoft account. When this function is executed, a web browser is launched to prompt for login. After logging in, the browser shows a page indicating that account authentication is complete. After ms login, this page printed "Authentication complete. You can return to the application. Feel free to close this browser tab."

And then, this is error content.

System.AggregateException HResult=0x80131500 message=One or more errors occurred. (A configuration issue is preventing authentication - check the error message from the server for details. You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'. Trace ID: ef0f8da8-2e8b-46ce-8ee5-227b97ea0d01 Correlation ID: e830675e-b28d-48ba-9683-7f4c9bce98c1 Timestamp: 2024-07-10 09:00:43Z) source=System.Private.CoreLib StackTrace: System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) System.Threading.Tasks.Task1.get_Result()

throw.

1: MsalServiceException: A configuration issue is preventing authentication - check the error message from the server for details. You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'. Trace ID: ef0f8da8-2e8b-46ce-8ee5-227b97ea0d01 Correlation ID: e830675e-b28d-48ba-9683-7f4c9bce98c1 Timestamp: 2024-07-10 09:00:43Z

I refer to

var app = PublicClientApplicationBuilder.Create("YOUR_CLIENT_ID")
    .WithDefaultRedirectUri()
    .Build();

var accounts = await app.GetAccountsAsync();

AuthenticationResult result;
try
{
    result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
      .ExecuteAsync();
}
catch (MsalUiRequiredException)
{
    result = await app.AcquireTokenInteractive(scopes).ExecuteAsync();
}

Solution

  • I agree with @TinyWang, PublicClientApplicationBuilder does not require client secret. Refer this MS Document.

    The error occurs if you missed enabling public client flow option or added redirect URI in platforms other than "Mobile&Desktop application".

    I have one app registration where I added redirect URI in Web platform like this:

    enter image description here

    Initially, I too got same error in console when I ran below code with redirect URL in Web platform:

    var app = PublicClientApplicationBuilder.Create(clientId)
        .WithRedirectUri(redirectUri)
        .WithTenantId(tenantId)
        .Build();
    
    var accounts = await app.GetAccountsAsync();
    AuthenticationResult authResult = null;
    
    try
    {
        authResult = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        authResult = await app.AcquireTokenInteractive(scopes)
            .ExecuteAsync();
    }
    
    var token = authResult.AccessToken;
    Console.WriteLine($"Access Token: {token}");
    

    Browser authentication:

    enter image description here

    Error:

    enter image description here

    To resolve the error, make sure to enable public client flow option and add redirect URI in Mobile and desktop applications platform by removing it from other platforms:

    enter image description here

    When I ran the code again after making these changes, I got the access token successfully as below:

    using Microsoft.Identity.Client;
    
    class Program
    {
        private static string clientId = "appId";
        private static string tenantId = "tenantId";
        private static string redirectUri = "http://localhost";
        private static string[] scopes = new string[] { "User.Read" };
    
        static async Task Main(string[] args)
        {
            var app = PublicClientApplicationBuilder.Create(clientId)
                .WithRedirectUri(redirectUri)
                .WithTenantId(tenantId)
                .Build();
    
            var accounts = await app.GetAccountsAsync();
            AuthenticationResult authResult = null;
    
            try
            {
                authResult = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
                    .ExecuteAsync();
            }
            catch (MsalUiRequiredException)
            {
                authResult = await app.AcquireTokenInteractive(scopes)
                    .ExecuteAsync();
            }
    
            var token = authResult.AccessToken;
            Console.WriteLine($"Access Token: {token}");
        }
    }
    

    Response:

    enter image description here