Azure / azure-libraries-for-net

Azure libraries for .Net
MIT License
380 stars 192 forks source link

AzureCliCredentials throws 401 / AdalServiceException: AADSTS7000215: Invalid client secret is provided. #974

Open avishnyakov opened 4 years ago

avishnyakov commented 4 years ago

Describe the bug Hi team, can't get AzureCliCredentials working. It keeps throwing 401 / AdalServiceException: AADSTS7000215: Invalid client secret is provided.

Exception or Stack Trace Nothing much, just general System.AggregateException with 401 message HttpRequestException: Response status code does not indicate success: 401 (Unauthorized).

Inner Exception 3: AdalException: {"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret is provided.\r\nTrace ID: 13185846-a012-4fe2-83fb-2c6f718e1900\r\nCorrelation ID: c405535a-d02c-4a74-b67f-f73a3ea821be\r\nTimestamp: 2020-02-07 04:29:41Z","error_codes":[7000215],"timestamp":"2020-02-07 04:29:41Z","trace_id":"13185846-a012-4fe2-83fb-2c6f718e1900","correlation_id":"c405535a-d02c-4a74-b67f-f73a3ea821be","error_uri":"https://login.microsoftonline.com/error?code=7000215"}: Unknown error

To Reproduce Steps to reproduce the behavior:

Code Snippet

            var credentials = AzureCliCredentials.Create();
            credentials.WithDefaultSubscription("xx-yy");

            var client = new ApplicationInsightsManagementClient(credentials)
            {
                SubscriptionId = "xx-yy"
            };

            var apps = client.Components.ListAsync().Result;

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Setup (please complete the following information):

Additional context Add any other context about the problem here.

Information Checklist Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

avishnyakov commented 4 years ago

Okay. it seems that the current implementation does not check if at least one record of type "ServicePrincipal" was found in the corresponding az files and therefore, fails while trying to use default, non-initialized values for auth.

Probably the following bit of code should check for the presence of at least one "ServicePrincipal" records. We might have az working well with the current use yet never loging as a service principle, hence the "perception" of AzureCliCredentials not working.

I will leave this ticket open, we might want to throw exception asking folks to login as a service principle at least once. Also, it will use the currently selected, active-default subscription. Might be a good idea to add an option so we could use another subscription by name of id.

https://github.com/Azure/azure-libraries-for-net/blob/master/src/ResourceManagement/ResourceManager/Authentication/AzureCliCredentials.cs#L84

yaohaizh commented 4 years ago

Thanks for reporting this, We are routing to investigate.

xseeseesee commented 4 years ago

@avishnyakov Thanks for reporting this. For your case, it should be caused by the mismatched client id/secret pair. In your code snippet:

            var credentials = AzureCliCredentials.Create();
            credentials.WithDefaultSubscription("xx-yy");

We already have condition check to throw exception in this line if no ServicePrincipal found. The AdalServiceException would be thrown when "xx-yy" is not the default subscription in your account. Please use the az command az account set --subscription "xx-yy name" to switch to the subscription you want to use.

And for your suggestion, there will be a concern if you want to expose your subscription id in your code base or some files. The purpose to have such simple AzureCliCredentials.Create() was to keep your code base/project clean without exposing any credentials related.

mkosieradzki commented 4 years ago

I am facing a similiar issue.

I went through the code and I have a serious concern here:

https://github.com/Azure/azure-libraries-for-net/blob/master/src/ResourceManagement/ResourceManager/Authentication/AzureCliCredentials.cs#L54

How is this supposed to work? You are basically passing AccessToken as client secret for service principal..

xseeseesee commented 4 years ago

@mkosieradzki To use this feature, the user need to authenticate through Azure CLI first as per the introduction via command

az login --service-principal -u <app-url> -p <password> --tenant <tenant>

The naming here was because the AccessTokens.json created by Azure CLI. We might consider to change the property name to reduce the confusion.

grzegorz-wolszczak commented 4 years ago

(I use version Microsoft.Azure.Management.Fluent 1.34.0) question: does this AzureCliCredentials only applies to being logged as ServicePrincpal type only ?

I face issue like this : I use az login command, but I do not give additional parameters, which makes login interactive. When I'm logged in and type az account show i see

{
  "environmentName": "AzureCloud",
  "homeTenantId": "....",
  "id": "xxxx-some-id-xxx",
  "isDefault": true,
  "managedByTenants": [],
  "name": ".....",
  "state": "Enabled",
  "tenantId": ".....",
  "user": {
    "name": "........",
    "type": "user"
  }
}

So, My type is 'user' not a serviceprincipal. Then I have code like that

/* 1. */ var subscriptionId = "xxxx-some-id-xxx";
/* 2. */ var creds = AzureCliCredentials.Create();           
/* 3. */ var azure = Azure.Authenticate(creds).WithSubscription(subscriptionId);
/* 4. */ var resourceGroups = azure.VirtualMachines.List();

my subscription Id matched that from az account show and I get error like below Funny thing is that I got the exception from line 4 and not 3. So it happens when I actually try to query my azure object but authentication is successful.

Unhandled Exception: Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: AADSTS7000215: Invalid client secret is provided.
Trace ID: 1655904f-c033-449f-a3eb-8d591b3a0100
Correlation ID: f1fb58f5-9e9d-41db-93ad-b8cc22ad12d8
Timestamp: 2020-09-04 15:02:04Z ---> System.Net.Http.HttpRequestException: Response status code does not indicate success: 401 (Unauthorized). ---> Microsoft.IdentityModel.Clients.ActiveDirectory.AdalException: {"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret is provided.\r\nTr
ace ID: 1655904f-c033-449f-a3eb-8d591b3a0100\r\nCorrelation ID: f1fb58f5-9e9d-41db-93ad-b8cc22ad12d8\r\nTimestamp: 2020-09-04 15:02:04Z","error_codes":[7000215],"timestamp":"2020-09-04 15:02:04Z","trace_id":"1655904f-c033-449f-a3eb-8d591b3a0100","correlation_id":"f1fb58f5-9e9d-41db-93ad-b8cc22ad12d8","error_uri"
:"https://login.microsoftonline.com/error?code=7000215"}: Unknown error
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Http.AdalHttpClient.<GetResponseAsync>d__22`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Http.AdalHttpClient.<GetResponseAsync>d__21`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<SendHttpMessageAsync>d__68.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<SendTokenRequestAsync>d__65.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<CheckAndAcquireTokenUsingBrokerAsync>d__55.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.<RunAsync>d__53.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.<AcquireTokenForClientCommonAsync>d__36.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.<AcquireTokenAsync>d__65.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Rest.Azure.Authentication.Internal.MemoryApplicationAuthenticationProvider.<AuthenticateAsync>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Rest.Azure.Authentication.ApplicationTokenProvider.<LoginSilentAsync>d__37.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Rest.Azure.Authentication.ApplicationTokenProvider.<LoginSilentAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Rest.Azure.Authentication.ApplicationTokenProvider.<LoginSilentAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials.<ProcessHttpRequestAsync>d__24.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Azure.Management.Compute.Fluent.VirtualMachinesOperations.<ListAllWithHttpMessagesAsync>d__16.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Microsoft.Azure.Management.Compute.Fluent.VirtualMachinesOperationsExtensions.<ListAllAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.Azure.Management.Compute.Fluent.VirtualMachinesImpl.<ListInnerAsync>d__38.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.Azure.Management.ResourceManager.Fluent.Core.Extensions.Synchronize[TResult](Func`1 function)
   at Microsoft.Azure.Management.ResourceManager.Fluent.Core.TopLevelModifiableResources`5.List()
   at MainSandbox.Program.Main(String[] args) in D:\My\Projects.and.Repos\ProjectWithAttachedFolders\MainSandbox\Program.cs:line 49
xseeseesee commented 4 years ago

@grzegorz-wolszczak Yes, it's only for service principal. For user login, you may try with this.

grzegorz-wolszczak commented 4 years ago

@xccc-msft thanks for you response but does not help me actually. What you've send me is a code example, where I as user know my login and password. But I don't have them, because I login interactively, meaning that after typing az login I'm directed to https://login.microsoftonline.com/ from there I choose my account name and then I'm directed to my organizations (company signing page) which is external identity provider. (My company uses okta). Here I provide credentials (to my company identity provider) and if that is successful I got message in my browser like:

You have logged into Microsoft Azure!
You can close this window, or we will redirect you to the Azure CLI documents in 10 seconds.

From now on I can azure CLI without problems. but even though formally 'logged in' , I can't use Microsoft.Azure.Management.Fluent as I showed above.

xseeseesee commented 4 years ago

@grzegorz-wolszczak For your case, you may check AzureCliCredentials and create similar class (maybe named like AzureCliCredentialsForUserLogin) with scenario of parseing json and wrapping via SdkContext.AzureCredentialsFactory.FromUser.

grzegorz-wolszczak commented 4 years ago

@xccc-msft I would gladly do that but how. Which file should I parse ? After I'm logged by typing az login , from what I observed (please tell me If you know more about what happens) files that are 'updated' in %USERPROFILE% dir are accessToken.json and azureProfile.json. azureProfile.json has some data not related to authorization, and accessToken.json file is in format

[
    {
        "tokenType": "Bearer",
        "expiresIn": 3599,
        "expiresOn": "2020-09-08 10:15:15.670648",
        "resource": "https://management.core.windows.net/",
        "accessToken": "....",
        "oid": "....",
        "userId": "...",
        "isMRRT": true,
        "_clientId": "....",
        "_authority": "https://login.microsoftonline.com/common"
    },
    {
        "tokenType": "Bearer",
        "expiresIn": 3599,
        "expiresOn": "2020-09-08 10:15:17.114596",
        "resource": "https://management.core.windows.net/",
        "accessToken": "....",
        "oid": "....",
        "userId": "...",
        "isMRRT": true,
        "_clientId": "...",
        "_authority": "https://login.microsoftonline.com/...."
    }
]

FromUser function signature looks like FromUser(string username, string password, string clientId, string tenantId, AzureEnvironment environment). Which fields from accessToken.json should I pass to FromUser function arguments to make this work ?

xseeseesee commented 4 years ago

@grzegorz-wolszczak From azureProfile.json, you could find the info when you enter az account show. By parsing it, you could find your default account and get username/tenantId/environment(by environmentName). Then you can parse accessToken.json to get password/clientId by comparing _authority and tenantId.

grzegorz-wolszczak commented 4 years ago

ok, but what field from accessToken.json should be passed as password , content of accessToken field?

xseeseesee commented 4 years ago

@grzegorz-wolszczak Yes, accessToken. And for AzureCloud, it should be AzureEnvironment.AZURE.

JardarM commented 4 years ago

I use dotnet core libs and there does not seem to a be a FromUser method. How would I create the correct credentials then?

xseeseesee commented 4 years ago

@JardarM If so, would you consider to switch to service principal instead of user login?

ngarimella commented 3 years ago

Hitting the same issues after generating a new CLINET SECRET since the old one expired. Now we have no way to use this SP, which is embedded in several AMA offers.

Whats the update/workaround on this issue?

az login --service-principal -u $SYCOMP_CLIENT_ID -p $SYCOMP_CLIENT_SECRET --tenant $SYCOMP_TENANT_ID

Get Token request returned http error: 401 and server response: {"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret is provided.\r\nTrace ID: 720f0649-2147-4681-be5f-2db7d5a2f600\r\nCorrelation ID: 24e5fbf8-0461-4ccb-86b2-70298cb61988\r\nTimestamp: 2021-04-14 15:31:57Z","error_codes":[7000215],"timestamp":"2021-04-14 15:31:57Z","trace_id":"720f0649-2147-4681-be5f-2db7d5a2f600","correlation_id":"24e5fbf8-0461-4ccb-86b2-70298cb61988","error_uri":"https://login.microsoftonline.com/error?code=7000215"}

weidongxu-microsoft commented 3 years ago

For .NET, the development focus has shifted to the next generation of Azure SDKs which follows the new SDK guideline and introduces a set of important new features. Those new packages are currently in preview state and we are actively working on making it production ready. You can visit this link here to see the latest .NET packages: https://devblogs.microsoft.com/azure-sdk/october-2020-management-ga/

We have also published a few blog posts on why we are doing this: https://devblogs.microsoft.com/azure-sdk/introducing-new-previews-for-azure-management-libraries/

With this background, .NET Fluent is currently in a low maintenance mode, and we mostly do security and bug fixes. It is subject to deprecation in the future when the new set of .NET packages become Generally Available (GA). Please let us know if there are further questions, thanks!