Skip to content

Commit 1f870bf

Browse files
committed
Merge pull request Azure#1078 from markcowl/loginfix
Fix access token login and related issues [Fixes #105057182]
2 parents 5ce4649 + 4e7a1f8 commit 1f870bf

File tree

10 files changed

+191
-11
lines changed

10 files changed

+191
-11
lines changed

src/Common/Commands.Common/AzureRmProfileProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using Microsoft.Azure.Common.Authentication;
1516
using Microsoft.Azure.Common.Authentication.Models;
1617

1718
namespace Microsoft.WindowsAzure.Commands.Common

src/ResourceManager/Common/Commands.ResourceManager.Common/AzureRMCmdlet.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ public abstract class AzureRMCmdlet : AzurePSCmdlet
3737
/// </summary>
3838
static AzureRMCmdlet()
3939
{
40-
if (AzureSession.DataStore == null)
40+
if (!TestMockSupport.RunningMocked)
4141
{
4242
AzureSession.DataStore = new DiskDataStore();
43-
}
43+
}
4444
}
4545

4646
public AzureRMCmdlet()

src/ResourceManager/Profile/Commands.Profile/Account/AddAzureRmAccount.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,15 @@ public class AddAzureRMAccountCommand : AzureRMCmdlet , IModuleAssemblyInitializ
5555
[ValidateNotNullOrEmpty]
5656
public string AccessToken { get; set; }
5757

58-
[Parameter(Mandatory = false, HelpMessage = "Subscription")]
58+
[Parameter(ParameterSetName = "AccessToken", Mandatory = true, HelpMessage = "Account Id for access token")]
59+
[ValidateNotNullOrEmpty]
60+
public string AccountId { get; set; }
61+
62+
[Parameter(Mandatory = false, HelpMessage = "Subscription Id")]
5963
[ValidateNotNullOrEmpty]
6064
public string SubscriptionId { get; set; }
6165

62-
[Parameter(Mandatory = false, HelpMessage = "Subscription")]
66+
[Parameter(Mandatory = false, HelpMessage = "Subscription name")]
6367
[ValidateNotNullOrEmpty]
6468
public string SubscriptionName { get; set; }
6569

@@ -97,7 +101,14 @@ protected override void ProcessRecord()
97101

98102
if (!string.IsNullOrEmpty(AccessToken))
99103
{
104+
if (string.IsNullOrWhiteSpace(AccountId) )
105+
{
106+
throw new PSInvalidOperationException(Resources.AccountIdRequired);
107+
}
108+
100109
azureAccount.Type = AzureAccount.AccountType.AccessToken;
110+
azureAccount.Id = AccountId;
111+
azureAccount.SetProperty(AzureAccount.Property.AccessToken, AccessToken);
101112
}
102113
else if (ServicePrincipal.IsPresent)
103114
{
@@ -127,7 +138,8 @@ protected override void ProcessRecord()
127138

128139
var profileClient = new RMProfileClient(AzureRmProfileProvider.Instance.Profile);
129140

130-
WriteObject((PSAzureProfile)profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId, SubscriptionName, password));
141+
WriteObject((PSAzureProfile)profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId,
142+
SubscriptionName, password));
131143
}
132144

133145
/// <summary>

src/ResourceManager/Profile/Commands.Profile/Commands.Profile.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
<Compile Include="Models\PSAzureSubscription.cs" />
147147
<Compile Include="Models\PSAzureTenant.cs" />
148148
<Compile Include="Models\RMProfileClient.cs" />
149+
<Compile Include="Models\SimpleAccessToken.cs" />
149150
<Compile Include="Subscription\GetAzureRMSubscription.cs" />
150151
<Compile Include="Account\AddAzureRmAccount.cs" />
151152
<Compile Include="Context\GetAzureRMContext.cs" />

src/ResourceManager/Profile/Commands.Profile/Models/PSAzureProfile.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static implicit operator PSAzureProfile(AzureRMProfile profile)
3434
};
3535

3636
profile.Environments
37-
.ForEach((e) => result.Environments.Add(e.Key, (PSAzureEnvironment)e.Value));
37+
.ForEach((e) => result.Environments[e.Key] = (PSAzureEnvironment)e.Value);
3838
return result;
3939
}
4040

@@ -54,8 +54,7 @@ public static implicit operator AzureRMProfile(PSAzureProfile profile)
5454
{
5555
Context = profile.Context
5656
};
57-
profile.Environments
58-
.ForEach((e) => result.Environments.Add(e.Key, (AzureEnvironment)e.Value));
57+
profile.Environments.ForEach((e) => result.Environments[e.Key] = (AzureEnvironment) e.Value);
5958
return result;
6059
}
6160

src/ResourceManager/Profile/Commands.Profile/Models/PSAzureRmAccount.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,23 @@ public static implicit operator PSAzureRmAccount(AzureAccount account)
3636
return null;
3737
}
3838

39-
return new PSAzureRmAccount
39+
var result = new PSAzureRmAccount
4040
{
4141
Id = account.Id,
4242
AccountType = account.Type.ToString()
4343
};
44+
45+
if (account.IsPropertySet(AzureAccount.Property.AccessToken))
46+
{
47+
result.AccessToken = account.GetProperty(AzureAccount.Property.AccessToken);
48+
}
49+
50+
if (account.IsPropertySet(AzureAccount.Property.Tenants))
51+
{
52+
result.Tenants = account.GetProperty(AzureAccount.Property.Tenants);
53+
}
54+
55+
return result;
4456
}
4557

4658
/// <summary>
@@ -65,6 +77,16 @@ public static implicit operator AzureAccount(PSAzureRmAccount account)
6577
result.Type = accountType;
6678
}
6779

80+
if (!string.IsNullOrWhiteSpace(account.AccessToken))
81+
{
82+
result.SetProperty(AzureAccount.Property.AccessToken, account.AccessToken);
83+
}
84+
85+
if (!string.IsNullOrWhiteSpace(account.Tenants))
86+
{
87+
result.SetProperty(AzureAccount.Property.Tenants, account.Tenants);
88+
}
89+
6890
return result;
6991
}
7092

@@ -77,6 +99,16 @@ public static implicit operator AzureAccount(PSAzureRmAccount account)
7799
/// </summary>
78100
public string AccountType { get; set; }
79101

102+
/// <summary>
103+
/// The tenant ids for the account
104+
/// </summary>
105+
public string Tenants { get; set; }
106+
107+
/// <summary>
108+
/// The access token for the account (if any)
109+
/// </summary>
110+
public string AccessToken { get; set; }
111+
80112
public override string ToString()
81113
{
82114
return this.Id;

src/ResourceManager/Profile/Commands.Profile/Models/RMProfileClient.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
using System.Linq;
2626
using System.Management.Automation;
2727
using System.Security;
28+
using Microsoft.Azure.Commands.Profile.Models;
2829

2930
namespace Microsoft.Azure.Commands.ResourceManager.Common
3031
{
@@ -44,11 +45,13 @@ public RMProfileClient(AzureRMProfile profile)
4445
}
4546
}
4647

47-
public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId, string subscriptionName, SecureString password)
48+
public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId,
49+
string subscriptionName, SecureString password)
4850
{
4951
AzureSubscription newSubscription = null;
5052
AzureTenant newTenant = null;
51-
ShowDialog promptBehavior = password == null ? ShowDialog.Always : ShowDialog.Never;
53+
ShowDialog promptBehavior = (password == null && account.Type != AzureAccount.AccountType.AccessToken)
54+
? ShowDialog.Always : ShowDialog.Never;
5255

5356
// (tenant and subscription are present) OR
5457
// (tenant is present and subscription is not provided)
@@ -280,6 +283,12 @@ private IAccessToken AcquireAccessToken(AzureAccount account,
280283
SecureString password,
281284
ShowDialog promptBehavior)
282285
{
286+
if (account.Type == AzureAccount.AccountType.AccessToken)
287+
{
288+
tenantId = tenantId ?? "Common";
289+
return new SimpleAccessToken(account, tenantId);
290+
}
291+
283292
return AzureSession.AuthenticationFactory.Authenticate(
284293
account,
285294
environment,
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using System;
16+
using Microsoft.Azure.Commands.Profile.Properties;
17+
using Microsoft.Azure.Common.Authentication;
18+
using Microsoft.Azure.Common.Authentication.Models;
19+
20+
namespace Microsoft.Azure.Commands.Profile.Models
21+
{
22+
/// <summary>
23+
/// Provides access token information for a bearer token
24+
/// </summary>
25+
public class SimpleAccessToken : IAccessToken
26+
{
27+
public const string _defaultTokenType = "Bearer";
28+
private string _tokenType;
29+
30+
/// <summary>
31+
/// Create a new access token from the given account and tenant id
32+
/// </summary>
33+
/// <param name="account">The account, containing user id, access token information</param>
34+
/// <param name="tenantId">The tenant id for the given access token</param>
35+
/// <param name="tokenType">The token type for the given token.</param>
36+
public SimpleAccessToken(AzureAccount account, string tenantId, string tokenType = _defaultTokenType)
37+
{
38+
if (account == null)
39+
{
40+
throw new ArgumentNullException("account");
41+
}
42+
if (string.IsNullOrWhiteSpace(account.Id))
43+
{
44+
throw new ArgumentOutOfRangeException("account", Resources.AccessTokenRequiresAccount);
45+
}
46+
if (account.Type != AzureAccount.AccountType.AccessToken ||
47+
!account.IsPropertySet(AzureAccount.Property.AccessToken))
48+
{
49+
throw new ArgumentException(Resources.TypeNotAccessToken);
50+
}
51+
this.UserId = account.Id;
52+
this._tokenType = tokenType;
53+
this.AccessToken = account.GetProperty(AzureAccount.Property.AccessToken);
54+
this.TenantId = tenantId;
55+
}
56+
57+
58+
/// <summary>
59+
/// The access token to be applied to a request message
60+
/// </summary>
61+
public string AccessToken { get; private set; }
62+
63+
/// <summary>
64+
/// Authorize a request using an authorization setter function.
65+
/// </summary>
66+
/// <param name="authTokenSetter">The authorization token setter function.</param>
67+
public void AuthorizeRequest(System.Action<string, string> authTokenSetter)
68+
{
69+
authTokenSetter(_tokenType, AccessToken);
70+
}
71+
72+
/// <summary>
73+
/// The login type for this token
74+
/// </summary>
75+
public LoginType LoginType
76+
{
77+
get { return LoginType.OrgId; }
78+
}
79+
80+
/// <summary>
81+
/// The tenant Id for this token.
82+
/// </summary>
83+
public string TenantId { get; private set; }
84+
85+
/// <summary>
86+
/// The User Id associated with this token.
87+
/// </summary>
88+
public string UserId { get; private set; }
89+
}
90+
}

src/ResourceManager/Profile/Commands.Profile/Properties/Resources.Designer.cs

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ResourceManager/Profile/Commands.Profile/Properties/Resources.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@
117117
<resheader name="writer">
118118
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119119
</resheader>
120+
<data name="AccessTokenRequiresAccount" xml:space="preserve">
121+
<value>AccountId must be provided to use an AccessToken credential.</value>
122+
</data>
123+
<data name="AccountIdRequired" xml:space="preserve">
124+
<value>Access token credentials must provide the AccountId parameter.</value>
125+
</data>
120126
<data name="AzureProfileMustNotBeNull" xml:space="preserve">
121127
<value>Selected profile must not be null.</value>
122128
</data>
@@ -141,4 +147,7 @@
141147
<data name="TenantAuthFailed" xml:space="preserve">
142148
<value>Could not authenticate with tenant {0}. Please ensure that your account has access to this tenant and log in with Login-AzureRmAccount</value>
143149
</data>
150+
<data name="TypeNotAccessToken" xml:space="preserve">
151+
<value>To create an access token credential, you must provide an access token account.</value>
152+
</data>
144153
</root>

0 commit comments

Comments
 (0)