Skip to content

Fix access token login and related issues [Fixes #105057182] #1078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 7, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Common/Commands.Common/AzureRmProfileProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// limitations under the License.
// ----------------------------------------------------------------------------------

using Microsoft.Azure.Common.Authentication;
using Microsoft.Azure.Common.Authentication.Models;

namespace Microsoft.WindowsAzure.Commands.Common
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public abstract class AzureRMCmdlet : AzurePSCmdlet
/// </summary>
static AzureRMCmdlet()
{
if (AzureSession.DataStore == null)
if (!TestMockSupport.RunningMocked)
{
AzureSession.DataStore = new DiskDataStore();
}
}
}

public AzureRMCmdlet()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,15 @@ public class AddAzureRMAccountCommand : AzureRMCmdlet , IModuleAssemblyInitializ
[ValidateNotNullOrEmpty]
public string AccessToken { get; set; }

[Parameter(Mandatory = false, HelpMessage = "Subscription")]
[Parameter(ParameterSetName = "AccessToken", Mandatory = true, HelpMessage = "Account Id for access token")]
[ValidateNotNullOrEmpty]
public string AccountId { get; set; }

[Parameter(Mandatory = false, HelpMessage = "Subscription Id")]
[ValidateNotNullOrEmpty]
public string SubscriptionId { get; set; }

[Parameter(Mandatory = false, HelpMessage = "Subscription")]
[Parameter(Mandatory = false, HelpMessage = "Subscription name")]
[ValidateNotNullOrEmpty]
public string SubscriptionName { get; set; }

Expand Down Expand Up @@ -97,7 +101,14 @@ protected override void ProcessRecord()

if (!string.IsNullOrEmpty(AccessToken))
{
if (string.IsNullOrWhiteSpace(AccountId) )
{
throw new PSInvalidOperationException(Resources.AccountIdRequired);
}

azureAccount.Type = AzureAccount.AccountType.AccessToken;
azureAccount.Id = AccountId;
azureAccount.SetProperty(AzureAccount.Property.AccessToken, AccessToken);
}
else if (ServicePrincipal.IsPresent)
{
Expand Down Expand Up @@ -127,7 +138,8 @@ protected override void ProcessRecord()

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

WriteObject((PSAzureProfile)profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId, SubscriptionName, password));
WriteObject((PSAzureProfile)profileClient.Login(azureAccount, Environment, Tenant, SubscriptionId,
SubscriptionName, password));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
<Compile Include="Models\PSAzureSubscription.cs" />
<Compile Include="Models\PSAzureTenant.cs" />
<Compile Include="Models\RMProfileClient.cs" />
<Compile Include="Models\SimpleAccessToken.cs" />
<Compile Include="Subscription\GetAzureRMSubscription.cs" />
<Compile Include="Account\AddAzureRmAccount.cs" />
<Compile Include="Context\GetAzureRMContext.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static implicit operator PSAzureProfile(AzureRMProfile profile)
};

profile.Environments
.ForEach((e) => result.Environments.Add(e.Key, (PSAzureEnvironment)e.Value));
.ForEach((e) => result.Environments[e.Key] = (PSAzureEnvironment)e.Value);
return result;
}

Expand All @@ -54,8 +54,7 @@ public static implicit operator AzureRMProfile(PSAzureProfile profile)
{
Context = profile.Context
};
profile.Environments
.ForEach((e) => result.Environments.Add(e.Key, (AzureEnvironment)e.Value));
profile.Environments.ForEach((e) => result.Environments[e.Key] = (AzureEnvironment) e.Value);
return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,23 @@ public static implicit operator PSAzureRmAccount(AzureAccount account)
return null;
}

return new PSAzureRmAccount
var result = new PSAzureRmAccount
{
Id = account.Id,
AccountType = account.Type.ToString()
};

if (account.IsPropertySet(AzureAccount.Property.AccessToken))
{
result.AccessToken = account.GetProperty(AzureAccount.Property.AccessToken);
}

if (account.IsPropertySet(AzureAccount.Property.Tenants))
{
result.Tenants = account.GetProperty(AzureAccount.Property.Tenants);
}

return result;
}

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

if (!string.IsNullOrWhiteSpace(account.AccessToken))
{
result.SetProperty(AzureAccount.Property.AccessToken, account.AccessToken);
}

if (!string.IsNullOrWhiteSpace(account.Tenants))
{
result.SetProperty(AzureAccount.Property.Tenants, account.Tenants);
}

return result;
}

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

/// <summary>
/// The tenant ids for the account
/// </summary>
public string Tenants { get; set; }

/// <summary>
/// The access token for the account (if any)
/// </summary>
public string AccessToken { get; set; }

public override string ToString()
{
return this.Id;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using System.Linq;
using System.Management.Automation;
using System.Security;
using Microsoft.Azure.Commands.Profile.Models;

namespace Microsoft.Azure.Commands.ResourceManager.Common
{
Expand All @@ -44,11 +45,13 @@ public RMProfileClient(AzureRMProfile profile)
}
}

public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId, string subscriptionName, SecureString password)
public AzureRMProfile Login(AzureAccount account, AzureEnvironment environment, string tenantId, string subscriptionId,
string subscriptionName, SecureString password)
{
AzureSubscription newSubscription = null;
AzureTenant newTenant = null;
ShowDialog promptBehavior = password == null ? ShowDialog.Always : ShowDialog.Never;
ShowDialog promptBehavior = (password == null && account.Type != AzureAccount.AccountType.AccessToken)
? ShowDialog.Always : ShowDialog.Never;

// (tenant and subscription are present) OR
// (tenant is present and subscription is not provided)
Expand Down Expand Up @@ -280,6 +283,12 @@ private IAccessToken AcquireAccessToken(AzureAccount account,
SecureString password,
ShowDialog promptBehavior)
{
if (account.Type == AzureAccount.AccountType.AccessToken)
{
tenantId = tenantId ?? "Common";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can be moved to SimpleAccessToken and have an 2nd constructor that takes account and defaults tenant to "Common"

return new SimpleAccessToken(account, tenantId);
}

return AzureSession.AuthenticationFactory.Authenticate(
account,
environment,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

using System;
using Microsoft.Azure.Commands.Profile.Properties;
using Microsoft.Azure.Common.Authentication;
using Microsoft.Azure.Common.Authentication.Models;

namespace Microsoft.Azure.Commands.Profile.Models
{
/// <summary>
/// Provides access token information for a bearer token
/// </summary>
public class SimpleAccessToken : IAccessToken
{
public const string _defaultTokenType = "Bearer";
private string _tokenType;

/// <summary>
/// Create a new access token from the given account and tenant id
/// </summary>
/// <param name="account">The account, containing user id, access token information</param>
/// <param name="tenantId">The tenant id for the given access token</param>
/// <param name="tokenType">The token type for the given token.</param>
public SimpleAccessToken(AzureAccount account, string tenantId, string tokenType = _defaultTokenType)
{
if (account == null)
{
throw new ArgumentNullException("account");
}
if (string.IsNullOrWhiteSpace(account.Id))
{
throw new ArgumentOutOfRangeException("account", Resources.AccessTokenRequiresAccount);
}
if (account.Type != AzureAccount.AccountType.AccessToken ||
!account.IsPropertySet(AzureAccount.Property.AccessToken))
{
throw new ArgumentException(Resources.TypeNotAccessToken);
}
this.UserId = account.Id;
this._tokenType = tokenType;
this.AccessToken = account.GetProperty(AzureAccount.Property.AccessToken);
this.TenantId = tenantId;
}


/// <summary>
/// The access token to be applied to a request message
/// </summary>
public string AccessToken { get; private set; }

/// <summary>
/// Authorize a request using an authorization setter function.
/// </summary>
/// <param name="authTokenSetter">The authorization token setter function.</param>
public void AuthorizeRequest(System.Action<string, string> authTokenSetter)
{
authTokenSetter(_tokenType, AccessToken);
}

/// <summary>
/// The login type for this token
/// </summary>
public LoginType LoginType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: formatting

public LoginType LoginType { get { return LoginType.OrgId; } }

{
get { return LoginType.OrgId; }
}

/// <summary>
/// The tenant Id for this token.
/// </summary>
public string TenantId { get; private set; }

/// <summary>
/// The User Id associated with this token.
/// </summary>
public string UserId { get; private set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: add comments to the properties

}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AccessTokenRequiresAccount" xml:space="preserve">
<value>AccountId must be provided to use an AccessToken credential.</value>
</data>
<data name="AccountIdRequired" xml:space="preserve">
<value>Access token credentials must provide the AccountId parameter.</value>
</data>
<data name="AzureProfileMustNotBeNull" xml:space="preserve">
<value>Selected profile must not be null.</value>
</data>
Expand All @@ -141,4 +147,7 @@
<data name="TenantAuthFailed" xml:space="preserve">
<value>Could not authenticate with tenant {0}. Please ensure that your account has access to this tenant and log in with Login-AzureRmAccount</value>
</data>
<data name="TypeNotAccessToken" xml:space="preserve">
<value>To create an access token credential, you must provide an access token account.</value>
</data>
</root>