diff --git a/src/Accounts/Accounts/Accounts.format.ps1xml b/src/Accounts/Accounts/Accounts.format.ps1xml
index 60a05a222f74..ec0d3787fa7d 100644
--- a/src/Accounts/Accounts/Accounts.format.ps1xml
+++ b/src/Accounts/Accounts/Accounts.format.ps1xml
@@ -171,6 +171,35 @@
+
+ Microsoft.Azure.Commands.Profile.Models.PSAccessToken
+
+ Microsoft.Azure.Commands.Profile.Models.PSAccessToken
+
+
+
+
+
+
+ Token
+
+
+ ExpiresOn
+
+
+ Type
+
+
+ TenantId
+
+
+ UserId
+
+
+
+
+
+
Microsoft.Azure.Commands.Profile.Models.PSAzureSubscriptionPolicy
diff --git a/src/Accounts/Accounts/Az.Accounts.psd1 b/src/Accounts/Accounts/Az.Accounts.psd1
index 7d9b3f57f530..ce7b5ca2171b 100644
--- a/src/Accounts/Accounts/Az.Accounts.psd1
+++ b/src/Accounts/Accounts/Az.Accounts.psd1
@@ -106,7 +106,7 @@ CmdletsToExport = 'Disable-AzDataCollection', 'Disable-AzContextAutosave',
'Disconnect-AzAccount', 'Get-AzContextAutosaveSetting',
'Set-AzDefault', 'Get-AzDefault', 'Clear-AzDefault',
'Register-AzModule', 'Enable-AzureRmAlias', 'Disable-AzureRmAlias',
- 'Uninstall-AzureRm', 'Invoke-AzRestMethod'
+ 'Uninstall-AzureRm', 'Invoke-AzRestMethod', 'Get-AzAccessToken'
# Variables to export from this module
# VariablesToExport = @()
diff --git a/src/Accounts/Accounts/ChangeLog.md b/src/Accounts/Accounts/ChangeLog.md
index 57d4388cdded..9389507f3feb 100644
--- a/src/Accounts/Accounts/ChangeLog.md
+++ b/src/Accounts/Accounts/ChangeLog.md
@@ -18,6 +18,7 @@
- Additional information about change #1
-->
## Upcoming Release
+* Added new cmdlet `Get-AzAccessToken`
* Fixed an issue that error happens if user profile path is inaccessible
* Fixed an issue causing Write-Object error during Connect-AzAccount [#13419]
* Added parameter "ContainerRegistryEndpointSuffix" to: `Add-AzEnvironment`, `Set-AzEnvironment`
diff --git a/src/Accounts/Accounts/Models/PSAccessToken.cs b/src/Accounts/Accounts/Models/PSAccessToken.cs
new file mode 100644
index 000000000000..959de7f4255d
--- /dev/null
+++ b/src/Accounts/Accounts/Models/PSAccessToken.cs
@@ -0,0 +1,30 @@
+//
+// 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;
+
+namespace Microsoft.Azure.Commands.Profile.Models
+{
+ public class PSAccessToken
+ {
+ public string Token { get; set; }
+
+ public DateTimeOffset ExpiresOn { get; set; }
+
+ public string TenantId { get; set; }
+
+ public string UserId { get; set; }
+
+ public string Type { get; } = "Bearer";
+ }
+}
diff --git a/src/Accounts/Accounts/Properties/Resources.Designer.cs b/src/Accounts/Accounts/Properties/Resources.Designer.cs
index 998663f21f28..7e639f21e1cc 100644
--- a/src/Accounts/Accounts/Properties/Resources.Designer.cs
+++ b/src/Accounts/Accounts/Properties/Resources.Designer.cs
@@ -600,6 +600,15 @@ internal static string InvalidEndpointProvided {
}
}
+ ///
+ /// Looks up a localized string similar to The specified ResourceTypeName "{0}" is not supported, please provide a valid value. e.g. Arm, AadGraph, etc..
+ ///
+ internal static string InvalidResourceTypeName {
+ get {
+ return ResourceManager.GetString("InvalidResourceTypeName", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The provided subscription ID "{0}" is not a valid Guid..
///
diff --git a/src/Accounts/Accounts/Properties/Resources.resx b/src/Accounts/Accounts/Properties/Resources.resx
index b18d22752931..48a66d7b008a 100644
--- a/src/Accounts/Accounts/Properties/Resources.resx
+++ b/src/Accounts/Accounts/Properties/Resources.resx
@@ -519,6 +519,9 @@
Please run 'Connect-AzAccount -DeviceCode' if browser is not supported in this session.
+
+ The specified ResourceTypeName "{0}" is not supported, please provide a valid value. e.g. Arm, AadGraph, etc.
+
INITIALIZATION: Fallback context save mode to process because of error during checking token cache persistence: {0}.
diff --git a/src/Accounts/Accounts/Token/GetAzureRmAccessToken.cs b/src/Accounts/Accounts/Token/GetAzureRmAccessToken.cs
new file mode 100644
index 000000000000..d493f27787a4
--- /dev/null
+++ b/src/Accounts/Accounts/Token/GetAzureRmAccessToken.cs
@@ -0,0 +1,147 @@
+// ----------------------------------------------------------------------------------
+//
+// 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 System.Collections.Generic;
+using System.Management.Automation;
+
+using Microsoft.Azure.Commands.Common.Authentication;
+using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
+using Microsoft.Azure.Commands.Profile.Models;
+using Microsoft.Azure.Commands.ResourceManager.Common;
+using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
+using Microsoft.Azure.PowerShell.Authenticators;
+
+namespace Microsoft.Azure.Commands.Profile
+{
+ [Cmdlet(VerbsCommon.Get, AzureRMConstants.AzureRMPrefix + "AccessToken", DefaultParameterSetName = KnownResourceNameParameterSet)]
+ [OutputType(typeof(PSAccessToken))]
+ public class GetAzureRmAccessTokenCommand : AzureRMCmdlet
+ {
+ private const string ResourceUrlParameterSet = "ResourceUrl";
+ private const string KnownResourceNameParameterSet = "KnownResourceTypeName";
+
+ [Parameter(ParameterSetName = ResourceUrlParameterSet,
+ Mandatory = true,
+ HelpMessage = "Resource url for that you're requesting token, e.g. 'http://graph.windows.net/'.")]
+ [ValidateNotNullOrEmpty]
+ [Alias("Resource", "ResourceUri")]
+ public string ResourceUrl { get; set; }
+
+ [Parameter(ParameterSetName = KnownResourceNameParameterSet,
+ Mandatory = false,
+ HelpMessage = "Optional resouce type name, supported values: AadGraph, AnalysisServices, Arm, Attestation, Batch, DataLake, KeyVault, OperationalInsights, ResourceManager, Synapse. Default value is Arm if not specified.")]
+ [PSArgumentCompleter(
+ SupportedResourceNames.AadGraph,
+ SupportedResourceNames.AnalysisServices,
+ SupportedResourceNames.Arm,
+ SupportedResourceNames.Attestation,
+ SupportedResourceNames.Batch,
+ SupportedResourceNames.DataLake,
+ SupportedResourceNames.KeyVault,
+ SupportedResourceNames.ManagedHsm,
+ SupportedResourceNames.OperationalInsights,
+ SupportedResourceNames.ResourceManager,
+ SupportedResourceNames.Synapse
+ )]
+ public string ResourceTypeName { get; set; }
+
+ //Use tenant in default context if not specified
+ //TODO: Should not specify TenantId for MSI, CloudShell(?)
+ [Parameter(Mandatory = false, HelpMessage = "Optional Tenant Id. Use tenant id of default context if not specified.")]
+ public string TenantId { get; set; }
+
+ public override void ExecuteCmdlet()
+ {
+ base.ExecuteCmdlet();
+
+ string resourceUrlOrId;
+
+ if (ParameterSetName == KnownResourceNameParameterSet)
+ {
+ if (ResourceTypeName == null)
+ {
+ ResourceTypeName = SupportedResourceNames.Arm;
+ }
+ if (!SupportedResourceNames.ResourceNameMap.ContainsKey(ResourceTypeName))
+ {
+ throw new ArgumentException(Properties.Resources.InvalidResourceTypeName.FormatInvariant(ResourceTypeName), nameof(ResourceTypeName));
+ }
+ resourceUrlOrId = SupportedResourceNames.ResourceNameMap[ResourceTypeName];
+ }
+ else
+ {
+ resourceUrlOrId = ResourceUrl;
+ }
+
+ IAzureContext context = DefaultContext;
+ if(TenantId == null)
+ {
+ TenantId = context.Tenant?.Id;
+ }
+
+ IAccessToken accessToken = AzureSession.Instance.AuthenticationFactory.Authenticate(
+ context.Account,
+ context.Environment,
+ TenantId,
+ null,
+ ShowDialog.Never,
+ null,
+ null,
+ resourceUrlOrId);
+
+ var result = new PSAccessToken()
+ {
+ Token = accessToken.AccessToken,
+ TenantId = TenantId,
+ UserId = accessToken.UserId,
+ };
+ result.ExpiresOn = (accessToken as MsalAccessToken)?.ExpiresOn ?? result.ExpiresOn;
+
+ WriteObject(result);
+ }
+
+ internal class SupportedResourceNames
+ {
+ public const string Arm = "Arm";
+ public const string AadGraph = "AadGraph";
+ public const string Batch = "Batch";
+ public const string DataLake = "DataLake";
+ public const string KeyVault = "KeyVault";
+ public const string ResourceManager = "ResourceManager"; //endpoint is same as Arm
+
+ public const string AnalysisServices = "AnalysisServices";
+ public const string Attestation = "Attestation";
+ public const string OperationalInsights = "OperationalInsights";
+ public const string Synapse = "Synapse";
+ public const string ManagedHsm = "ManagedHsm";
+
+ internal static Dictionary ResourceNameMap = new Dictionary()
+ {
+ { Arm, AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId },
+ { AadGraph, AzureEnvironment.Endpoint.GraphEndpointResourceId },
+ { Batch, AzureEnvironment.Endpoint.BatchEndpointResourceId },
+ { DataLake, AzureEnvironment.Endpoint.DataLakeEndpointResourceId },
+ { KeyVault, AzureEnvironment.Endpoint.AzureKeyVaultServiceEndpointResourceId },
+ { ResourceManager, AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId },
+
+ { AnalysisServices, AzureEnvironment.ExtendedEndpoint.AnalysisServicesEndpointResourceId },
+ { Attestation, AzureEnvironment.ExtendedEndpoint.AzureAttestationServiceEndpointResourceId },
+ { OperationalInsights, AzureEnvironment.ExtendedEndpoint.OperationalInsightsEndpointResourceId },
+ { Synapse, AzureEnvironment.ExtendedEndpoint.AzureSynapseAnalyticsEndpointResourceId },
+ { ManagedHsm, AzureEnvironment.ExtendedEndpoint.ManagedHsmServiceEndpointResourceId }
+ };
+ }
+ }
+}
diff --git a/src/Accounts/Accounts/help/Az.Accounts.md b/src/Accounts/Accounts/help/Az.Accounts.md
index 40662c53cdef..b18d027df9a4 100644
--- a/src/Accounts/Accounts/help/Az.Accounts.md
+++ b/src/Accounts/Accounts/help/Az.Accounts.md
@@ -47,6 +47,9 @@ machine. Data is collected by default unless you explicitly opt out.
### [Enable-AzureRmAlias](Enable-AzureRmAlias.md)
Enables AzureRm prefix aliases for Az modules.
+### [Get-AzAccessToken](Get-AzAccessToken.md)
+Get raw access token.
+
### [Get-AzContext](Get-AzContext.md)
Gets the metadata used to authenticate Azure Resource Manager requests.
@@ -60,9 +63,6 @@ Get the defaults set by the user in the current context.
### [Get-AzEnvironment](Get-AzEnvironment.md)
Get endpoints and metadata for an instance of Azure services.
-### [Get-AzProfile](Get-AzProfile.md)
-Get the service profiles supported by installed modules.
-
### [Get-AzSubscription](Get-AzSubscription.md)
Get subscriptions that the current account can access.
@@ -96,9 +96,6 @@ Saves the current authentication information for use in other PowerShell session
### [Select-AzContext](Select-AzContext.md)
Select a subscription and account to target in Azure PowerShell cmdlets
-### [Select-AzProfile](Select-AzProfile.md)
-For modules that support multiple service profiles - load the cmdlets corresponding with the given service profile.
-
### [Send-Feedback](Send-Feedback.md)
Sends feedback to the Azure PowerShell team via a set of guided prompts.
diff --git a/src/Accounts/Accounts/help/Get-AzAccessToken.md b/src/Accounts/Accounts/help/Get-AzAccessToken.md
new file mode 100644
index 000000000000..5c09aa4ccdec
--- /dev/null
+++ b/src/Accounts/Accounts/help/Get-AzAccessToken.md
@@ -0,0 +1,128 @@
+---
+external help file: Microsoft.Azure.PowerShell.Cmdlets.Accounts.dll-Help.xml
+Module Name: Az.Accounts
+online version: https://docs.microsoft.com/en-us/powershell/module/az.accounts/get-azaccesstoken
+schema: 2.0.0
+---
+
+# Get-AzAccessToken
+
+## SYNOPSIS
+Get raw access token. When using -ResourceUrl, please make sure the value does match current Azure environment. You may refer to the value of `(Get-AzContext).Environment`.
+
+## SYNTAX
+
+### KnownResourceTypeName (Default)
+```
+Get-AzAccessToken [-ResourceTypeName ] [-TenantId ] [-DefaultProfile ]
+ []
+```
+
+### ResourceUrl
+```
+Get-AzAccessToken -ResourceUrl [-TenantId ] [-DefaultProfile ]
+ []
+```
+
+## DESCRIPTION
+Get access token
+
+## EXAMPLES
+
+### Example 1 Get raw access token for ARM endpoint
+```powershell
+PS C:\> Get-AzAccessToken
+```
+
+Get access token of ResourceManager endpoint for current account
+
+### Example 2 Get raw access token for AAD graph endpoint
+```powershell
+PS C:\> Get-AzAccessToken -ResourceTypeName AadGraph
+```
+
+Get access token of AAD graph endpoint for current account
+
+### Example 3 Get raw access token for AAD graph endpoint
+```powershell
+PS C:\> Get-AzAccessToken -Resource "https://graph.windows.net/"
+```
+
+Get access token of AAD graph endpoint for current account
+
+## PARAMETERS
+
+### -DefaultProfile
+The credentials, account, tenant, and subscription used for communication with Azure.
+
+```yaml
+Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer
+Parameter Sets: (All)
+Aliases: AzContext, AzureRmContext, AzureCredential
+
+Required: False
+Position: Named
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -ResourceTypeName
+Optional resouce type name, supported values: AadGraph, AnalysisServices, Arm, Attestation, Batch, DataLake, KeyVault, OperationalInsights, ResourceManager, Synapse. Default value is Arm if not specified.
+
+```yaml
+Type: System.String
+Parameter Sets: KnownResourceTypeName
+Aliases:
+
+Required: False
+Position: Named
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -ResourceUrl
+Resource url for that you're requesting token, e.g. 'http://graph.windows.net/'.
+
+```yaml
+Type: System.String
+Parameter Sets: ResourceUrl
+Aliases: Resource, ResourceUri
+
+Required: True
+Position: Named
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -TenantId
+Optional Tenant Id. Use tenant id of default context if not specified.
+
+```yaml
+Type: System.String
+Parameter Sets: (All)
+Aliases:
+
+Required: False
+Position: Named
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### CommonParameters
+This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
+
+## INPUTS
+
+### None
+
+## OUTPUTS
+
+### System.String
+
+## NOTES
+
+## RELATED LINKS
diff --git a/src/Accounts/Authenticators/MsalAccessToken.cs b/src/Accounts/Authenticators/MsalAccessToken.cs
index b2480c7ca632..e66da95738dc 100644
--- a/src/Accounts/Authenticators/MsalAccessToken.cs
+++ b/src/Accounts/Authenticators/MsalAccessToken.cs
@@ -39,7 +39,7 @@ public class MsalAccessToken : IAccessToken
public IDictionary ExtendedProperties { get; } = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase);
- private DateTimeOffset ExpiredOn { get; set; }
+ public DateTimeOffset ExpiresOn { get; set; }
private readonly static TimeSpan ExpirationThreshold = TimeSpan.FromMinutes(5);
@@ -53,7 +53,7 @@ public MsalAccessToken(TokenCredential tokenCredential, TokenRequestContext toke
TokenCredential = tokenCredential;
TokenRequestContext = tokenRequestContext;
AccessToken = token;
- ExpiredOn = expiresOn;
+ ExpiresOn = expiresOn;
UserId = userId;
TenantId = tenantId;
HomeAccountId = homeAccountId;
@@ -98,7 +98,7 @@ private void Renew()
{
var token = TokenCredential.GetToken(TokenRequestContext, default(CancellationToken));
AccessToken = token.Token;
- ExpiredOn = token.ExpiresOn;
+ ExpiresOn = token.ExpiresOn;
}
}
@@ -110,7 +110,7 @@ private bool IsNearExpiration()
return true;
}
#endif
- var timeUntilExpiration = ExpiredOn - DateTimeOffset.UtcNow;
+ var timeUntilExpiration = ExpiresOn - DateTimeOffset.UtcNow;
return timeUntilExpiration < ExpirationThreshold;
}
}