Hero Banner

Secure Application Model

Learn and ask questions on how to implement secure application model

Reply
ashin
Level 1 Contributor

Connect-AzureAD to Other Tenants with Secure Application Model

Hello! Is it possible to use Connect-AzureAD to connect to other tenants using the secure application model? Connect-AzureAD goes through for me, but when attempting to run something like Get-AzureADUser, I get the following error:

get-azureaduser : Error occurred while executing GetUsers
Code: Request_BadRequest
Message: Invalid domain name in the request url.
RequestId: 84f9ac40-c6cb-4a58-beaf-b69dd1038b5e
DateTimeStamp: Sun, 21 Jul 2019 21:18:23 GMT
HttpStatusCode: BadRequest
HttpStatusDescription: Bad Request
HttpResponseStatus: Completed
At line:1 char:1
+ get-azureaduser
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-AzureADUser], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.GetUser

Thanks in advance!

18 REPLIES 18
pavlekukric
Level 1 Contributor

Using this https://docs.microsoft.com/en-us/powershell/partnercenter/multi-factor-auth?view=partnercenterps-3.0 , I was able to connect to Exchange Online PowerShell , but when try

 

'Connect-MsolService -AdGraphAccessToken $aadGraphToken.AccessToken -MsGraphAccessToken $graphToken.AccessToken' generic exception is shown without any useful info.


Exception: FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.InvalidHeaderException,Microsoft.Online.Administration.Automation.ConnectMsolService

 

Please note that I was able to retrieve MsGraphAccessToken and AdGraphAccessToken , but when try to call Connect-MsolService .... problem occurs.

 

$credential = Get-Credential - I'm using application Id and client secret of my Azure application of my partner account.

 

$refreshToken = '<RefreshToken>' - Is the result of consent process after executing: New-PartnerAccessToken -ApplicationId' applicationIdOfMyPartnerAccount' -Scopes 'https://api.partnercenter.microsoft.com/user_impersonation' -
ServicePrincipal -Credential $credential -Tenant 'tenantIdOfOneOfMyTenants' -UseAuthorizationCode

 

$aadGraphToken = New-PartnerAccessToken -ApplicationId 'applicationIdOfMyPartnerAccount' -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.windows.net/.default' -ServicePrincipal -Tenant 'tenantIdOfOneOfMyTenants'

 

$graphToken = New-PartnerAccessToken -ApplicationId 'applicationIdOfMyPartnerAccount' -Credential $credential -
RefreshToken $refreshToken -Scopes 'https://graph.microsoft.com/.default' -ServicePrincipal -Tenant
'tenantIdOfOneOfMyTenants'

 

Also, Azure application has all required permissions. I've created it using powershell script from https://docs.microsoft.com/en-gb/powershell/partnercenter/secure-app-model?view=partnercenterps-1.5#feedback

Also, I've created additional redirect "url http://localhost:8400" as it stated here because newer version require this as redirect url.

Any info will be useful.

 

Thank you.

sansbacher
Level 6 Contributor

Hello @pavlekukric 

 

I think the issue is probably your Tenant IDs. If you are trying to use Delegated Admin Permissions (DAP) - that is: connect to your clients/customers that you have permission to administer then you initially need to create the RefreshToken using YOUR TenantID. Then you connect and retrieve the AAD and Graph Tokens using YOUR TenantID, finally you connect to the desired client/customer Tenant using tenantIdOfOneOfYourClients.

 

It looks like you are trying to connect to tenantIdOfOneOfYourClients too early. For MSOnline/Msol you only use tenantIdOfOneOfYourClients when running any Get-Msol* type commands ON THE CUSTOMER; all the other commands use YOUR TenantID.

 

I had initially tried to follow the official MS docs (that you linked) and I couldn't get it to work. Kelvin managed to get it working using DAP to access clients for Exchange Online and MS Online, and I worked out the AzureAD part. I recently spoke with MS support (about a different issue) and confirmed that the script Kelvin created (which is based on Isaiah's original MS script) is functionally correct.

 

I would strongly suggest you follow those instructions and try again (making a new Azure App and getting a new Refresh Token):

Review the thread at: https://www.microsoftpartnercommunity.com/t5/Secure-Application-Model/Exchange-Online-and-the-Secure-App-Model/td-p/11771 

 

See KelvinTegelaar's comment on Nov 14 2019 at 03:53 PM where he links to:

https://www.cyberdrain.com/connect-to-exchange-online-automated-when-mfa-is-enabled-using-the-secureapp-model/ 

 

Then see my expanded comment on Jan 7 2020 at 09:38 AM which explains all the steps.  (also the very last comment of mine in that thread, on the second page, has a slightly edited version of Kelvin's script attached. You can use that if you'd prefer - it's a little more explicit).

 

My comment from Jan 7th show all the steps, including connecting to a customer for each of Exch Online, Msol, and AzureAD. You'll see that $TenantID is used initially (which is MY TenantID) and then later $Customer.CustomerContextId to connect to the Client (which is the Tenant ID of one of my Clients).

 

Two more notes: With Msol commands you need to specify -Tenant $Customer.CustomerContextId for every command when dealing with client connections. With Azure AD you don't have to, so I would recommend using AzureAD where possible (everything except MFA I think). The Azure AD initial connection is a few extra steps, but worth it in the long run.

 

If you're still having issues let me know!

   --Saul

 

katareamol
Visitor 1

Hi
When running PowerShell scripts, I received an error. 


 Connect-MsolService : Authentication Error: Unexpected authentication failure.

At line:2 char:1

+ Connect-MsolService -Credential $credential

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : OperationStopped: (:) [Connect-MsolService], Exception

    + FullyQualifiedErrorId : System.Exception,Microsoft.Online.Administration.Automation.ConnectMsolService

 

New-PSSession : [outlook.office365.com] Connecting to remote server outlook.office365.com failed with the following error message : Access is denied. For more information, see the about_Remote_Troubleshooting Help topic.

At line:3 char:20

+ ... geSession = New-PSSession -ConfigurationName Microsoft.Exchange -Conn ...

+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException

    + FullyQualifiedErrorId : AccessDenied,PSSessionOpenFailed

Import-PSSession : Cannot validate argument on parameter 'Session'. The argument is null. Provide a valid value for the argument, and then try running the command again.

At line:5 char:18

+ Import-PSSession $exchangeSession -DisableNameChecking

+                  ~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Import-PSSession], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.ImportPSSessionCommand 

sansbacher
Level 6 Contributor

Hi @katareamol ,

 

I would suggest you start a NEW thread/question in these forums - unless your problem is directly related to what was discussed in this thread. It will have much better visibility and be more likely to be answered, rather than hidden in an existing thread.

 

Also you'll need to provide the script/commands you are trying to run, not just the errors. And indicate if it used to work, or has never worked, and what you've tried, etc. How you connect to the MS online services (Msol, AzureAD, ExO, Azure, etc) matters a great deal.

 

  --Saul

v-jillarmour
Community Manager

@katareamol Tracking this string to make sure we get an answer for you. 

pavlekukric
Level 1 Contributor

@sansbacher  

I owe you a beer, actually I owe you two beers, I actually owe you ... actually choose how much do you want 😂

It works! 

Thank you very much!!!

I think that MS should write 'cleaner' documentation. I do not like the fact that we need to go trough the forums and read other people experiences and spend hours to be able to find some 'basic' info about this approach. I far as I can see, I'm not the only one who had problems with applying Secure application model.

Anyway, thanks again for your help!

Cheers!

 

Pavle Kukric   

 

 

sansbacher
Level 6 Contributor

You're welcome, glad it's working now!!

 

If you've ever in Canada (or if I'm in Europe again) I'm always game for a beer - just about anything local/craft 🙂

 

But I agree: this should all be collected up and rolled into some official MS PowerShell modules and documentation. Maybe the new Exchange Online V2 PS module will eventually include the ability to do all this with a few simple commands - including creating all the Azure Apps and prompting for the consent, etc.

 

Or maybe there's not many of us automating these sorts of things so there's no big demand? I dunno...

 

Have a great weekend!

   --Saul

idwilliams
Moderator

@ashin it possible, however, you need to be sure your Azure AD application is setup correctly. When up setup everything did you follow the guidance available here

sansbacher
Level 6 Contributor

Hi @idwilliams 

I am having the same problem. I believe my App is set up correctly (is there a way to confirm?) I followed: https://github.com/microsoft/Partner-Center-PowerShell#Native-App

 

I am able to use it with AppPlusUser rights to connect to the Partner Center and access Subscription and Licensing info.

 

I can also use it with the older ver 1 Msol/MS Online cmdlets to access Other Tenants, more or less as per:

https://docs.microsoft.com/en-us/powershell/partnercenter/multi-factor-auth?view=partnercenterps-1.5

 

After getting the RefreshToken, AppId, AppSecret, then New-PartnerAccessToken and Connect-PartnerCenter. I get the aadGraph and graph tokens. I can then use Connect-MsolService to connect to my tenancy, then Get-MsolPartnerContract to get a list of my Client/Customers, and use commands such as Get-MsolUser -TenantId <someClientTenantId> -- that works.

 

But if I use Connect-AzureAD instead, that will connect to MY Tenancy, and I can use Get-AzureAdContract to see my Clients/Customers. BUT... I can't work out how to use Connect-AzureAD again to connect to the CLIENT tenancy, whatever I do may work, but then Get-AzureAdUser returns as above: 

Get-AzureADUser : Error occurred while executing GetUsers
Code: Request_BadRequest
Message: Invalid domain name in the request url.

 

How can we use the new MFA-enabled Secure Application Model to connect to our client/customer AzureAD Tenancies and use the AzureAD cmdlets? (not the older, deprecated Msol ones). 

 

Do you have an example of this working? Thanks so much,

   -Saul

sansbacher
Level 6 Contributor

Has anyone worked this out with the AzureAD module / Delegated Admin / Secure App Module / MFA?

 

I just updated to the latest versions of AzureAD and PartnerCenter modules and the same problem: I can connect to PartnerCenter, get an AccessToken from a RefreshToken and connect to OUR (partner) AzureAD, then get a list of all our CLIENTS (using Get-AzureADContract) but I CANNOT connect to the client's AzureAD. No matter what I try for the Connect-AzureAD I can't connect to their tenant. I get the Request_BadRequest for any other AzureAD cmdlets.

 

Using older MsOnline module works (Get-MsolUser).

 

@daokeefe This is the issue I mentioned in the other thread. So when MS fixes the Exch Online PowerShell module to support the Secure App Model I hope they also fix this as I've already migrated all my scripts using Delegated Admin from Msol to AzureAD!

 

Thanks,

   --Saul

 

 

idwilliams
Moderator

@ashin and @sansbacher when you connect using the Azure AD PowerShell module you will need to specify the tenant where you to connect. The following code snippet should help.

 

$credential = Get-Credential
$refreshToken = 'Your-Refresh-Token-Value'

$aadGraphToken = New-PartnerAccessToken -RefreshToken $refreshToken -Resource https://graph.windows.net -Credential $credential -TenantId 'xxxx-xxxx-xxxx-xxxx'
$graphToken =  New-PartnerAccessToken -RefreshToken $refreshToken -Resource https://graph.microsoft.com -Credential $credential -TenantId 'xxxx-xxxx-xxxx-xxxx'

Connect-AzureAD -AadAccessToken $aadGraphToken.AccessToken -AccountId 'user@contoso.com' -MsAccessToken $graphToken.AccessToken -TenantId 'xxxx-xxxx-xxxx-xxxx'

Note that xxxx-xxxx-xxxx-xxxx should be the customer identifier where you want to connect.

sansbacher
Level 6 Contributor

Thanks @idwilliams , unfortunately I still cannot connect with AzureAD using this method - unless I'm missing something (or you're missing the Connect-PartnerCenter step). 

 

When I try your method and then call Get-AzureADUser I get:

Get-AzureADUser : Error occurred while executing GetUsers
Code: Authorization_IdentityNotFound
Message: The identity of the calling application could not be established.

 

I did what you suggested: 

Get-Credential # for this I used the NativeApp ID and the SharedSecret (which normally allows AppPlusUser access when it works)

$refreshToken   # I used a known working Refresh_Token

-TenantId    # for all 3 I used a confirmed Tenant / Microsoft ID of a client in our CSP Partner Center

-AccountId   # for this I used the username@domain.com in OUR tenant that has Account Admin permissions in the Partner Center that I used for the consent process.

[Is all that correct?]

 

And it didn't work. I also tried calling Connect-PartnerCenter but I get "Unauthorized access".

 

What I want to do: connect to the Partner Center, get a list of all Contracts/Clients and then connect to THEIR tenants (using Delegated Admin) to do stuff for each client. 

 

This works if I use commands similar to what you provided, but the -TenatID must be MY (partner) tenantID, and then use Connect-MsolService (with the aadGraph and MsGraph Tokens). I can then use Get-MsolUser -all -TenantId 'tenant-id-of-CLIENT-account'. 

 

But trying to do something similar with the AzureAD module doesn't work.  (but it does work if NOT using the Secure App Model, if I just use regular Delegated Admin).

 

Do you have any further suggestions? Thanks so much!

idwilliams
Moderator

You will receive this error if you have not configured the Azure AD application to available to all organizational directories and if it has not been configured for pre-consent. You can use the following PowerShell code to create an Azure AD application that will work 

 

<#
    .SYNOPSIS
        This script will create the require Azure AD application.
    .EXAMPLE
        .\Create-AzureADApplication.ps1 -ConfigurePreconsent -DisplayName "Partner Center Web App"

        .\Create-AzureADApplication.ps1 -ConfigurePreconsent -DisplayName "Partner Center Web App" -TenantId eb210c1e-b697-4c06-b4e3-8b104c226b9a

        .\Create-AzureADApplication.ps1 -ConfigurePreconsent -DisplayName "Partner Center Web App" -TenantId tenant01.onmicrosoft.com
    .PARAMETER ConfigurePreconsent
        Flag indicating whether or not the Azure AD application should be configured for preconsent.
    .PARAMETER DisplayName
        Display name for the Azure AD application that will be created.
    .PARAMETER TenantId
        [OPTIONAL] The domain or tenant identifier for the Azure AD tenant that should be utilized to create the various resources.
#>

Param
(
    [Parameter(Mandatory = $true)]
    [switch]$ConfigurePreconsent,
    [Parameter(Mandatory = $true)]
    [string]$DisplayName,
    [Parameter(Mandatory = $false)]
    [string]$TenantId
)

$ErrorActionPreference = "Stop"

# Check if the Azure AD PowerShell module has already been loaded.
if ( ! ( Get-Module AzureAD ) ) {
    # Check if the Azure AD PowerShell module is installed.
    if ( Get-Module -ListAvailable -Name AzureAD ) {
        # The Azure AD PowerShell module is not load and it is installed. This module
        # must be loaded for other operations performed by this script.
        Write-Host -ForegroundColor Green "Loading the Azure AD PowerShell module..."
        Import-Module AzureAD
    } else {
        Install-Module AzureAD
    }
}

try {
    Write-Host -ForegroundColor Green "When prompted please enter the appropriate credentials..."

    if([string]::IsNullOrEmpty($TenantId)) {
        Connect-AzureAD | Out-Null

        $TenantId = $(Get-AzureADTenantDetail).ObjectId
    } else {
        Connect-AzureAD -TenantId $TenantId | Out-Null
    }
} catch [Microsoft.Azure.Common.Authentication.AadAuthenticationCanceledException] {
    # The authentication attempt was canceled by the end-user. Execution of the script should be halted.
    Write-Host -ForegroundColor Yellow "The authentication attempt was canceled. Execution of the script will be halted..."
    Exit
} catch {
    # An unexpected error has occurred. The end-user should be notified so that the appropriate action can be taken.
    Write-Error "An unexpected error has occurred. Please review the following error message and try again." `
        "$($Error[0].Exception)"
}

$adAppAccess = [Microsoft.Open.AzureAD.Model.RequiredResourceAccess]@{
    ResourceAppId = "00000002-0000-0000-c000-000000000000";
    ResourceAccess =
    [Microsoft.Open.AzureAD.Model.ResourceAccess]@{
        Id = "5778995a-e1bf-45b8-affa-663a9f3f4d04";
        Type = "Role"},
    [Microsoft.Open.AzureAD.Model.ResourceAccess]@{
        Id = "a42657d6-7f20-40e3-b6f0-cee03008a62a";
        Type = "Scope"},
    [Microsoft.Open.AzureAD.Model.ResourceAccess]@{
        Id = "311a71cc-e848-46a1-bdf8-97ff7156d8e6";
        Type = "Scope"}
}

$graphAppAccess = [Microsoft.Open.AzureAD.Model.RequiredResourceAccess]@{
    ResourceAppId = "00000003-0000-0000-c000-000000000000";
    ResourceAccess =
        [Microsoft.Open.AzureAD.Model.ResourceAccess]@{
            Id = "bf394140-e372-4bf9-a898-299cfc7564e5";
            Type = "Role"},
        [Microsoft.Open.AzureAD.Model.ResourceAccess]@{
            Id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61";
            Type = "Role"}
}

$partnerCenterAppAccess = [Microsoft.Open.AzureAD.Model.RequiredResourceAccess]@{
    ResourceAppId = "fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd";
    ResourceAccess =
        [Microsoft.Open.AzureAD.Model.ResourceAccess]@{
            Id = "1cebfa2a-fb4d-419e-b5f9-839b4383e05a";
            Type = "Scope"}
}

$SessionInfo = Get-AzureADCurrentSessionInfo

Write-Host -ForegroundColor Green "Creating the Azure AD application and related resources..."

$app = New-AzureADApplication -AvailableToOtherTenants $true -DisplayName $DisplayName -IdentifierUris "https://$($SessionInfo.TenantDomain)/$((New-Guid).ToString())" -RequiredResourceAccess $adAppAccess, $graphAppAccess, $partnerCenterAppAccess -ReplyUrls @("urn:ietf:wg:oauth:2.0:oob")
$password = New-AzureADApplicationPasswordCredential -ObjectId $app.ObjectId
$spn = New-AzureADServicePrincipal -AppId $app.AppId -DisplayName $DisplayName

if($ConfigurePreconsent) {
    $adminAgentsGroup = Get-AzureADGroup -Filter "DisplayName eq 'AdminAgents'"
    Add-AzureADGroupMember -ObjectId $adminAgentsGroup.ObjectId -RefObjectId $spn.ObjectId
}

Write-Host "ApplicationId       = $($app.AppId)"
Write-Host "ApplicationSecret   = $($password.Value)"
sansbacher
Level 6 Contributor

As a note for @ashin and @Gavsto - if you are still getting errors trying to use Connect-AzureAd / Get-AzureAdUser for CLIENT/CUSTOMER tenants that you have Delegated Permissions to: a solution has been found.

 

@KelvinTegelaar worked out how to do it for Exchange Online and has a blog post here:

https://www.cyberdrain.com/connect-to-exchange-online-automated-when-mfa-is-enabled-using-the-secureapp-model/ 

 

His main script is a variation of @idwilliams 's Create-AzureADApplication.ps1 script - except it adds some Exchange Online stuff (permissions and a second Refresh Token). Kelvin then shows how to connect to your customer's Exchange Online with delegated permissions (which works).

 

I couldn't do the same with Azure AD, I was still getting:

Get-AzureADUser : Error occurred while executing GetUsers
Code: Request_BadRequest
Message: Invalid domain name in the request url.

 

But then I combined his Exch Online method of getting a new token with Azure AD and it worked! See my comment at the end of this thread:

https://www.microsoftpartnercommunity.com/t5/Secure-Application-Model/Exchange-Online-and-the-Secure-App-Model/m-p/15136#M121 

(also posted as a comment on his Blog)

 

Basically you need to get the Graph and AzureAD Tokens, Connect-AzureAd to your (CSP) Tenant, get all your customers (and their TenantIDs). Disconnect-AzureAd.  Then for each Customer you need to acquire NEW Graph and AAD Tokens using the Customer's TenantId, then connect to AzureAd using those new Customer Tokens.

 

I was then able to use Get-AzureAdUser to get all the Users of a Client/Customer without error. Hope that helps!

    --Saul

 

sansbacher
Level 6 Contributor

Has anyone had any luck with this? Any word from Microsoft? @idwilliams or @daokeefe ??

Gavsto
Level 3 Contributor

Did you guys ever get an answer to this?

I have hit the same stumbling block.

 

This implementation of the Secure App Model for Powershell has been an absolute disgrace and Microsoft should be ashamed of the awful service they are providing to their partners.

 

1 and a half months and no answer. Disgusting.

JanoschUlmer
Microsoft

Alternatively to this community - If you need 1:1 technical advisory guidance on how to work with the secure app model, you can always contact askpts@microsoft.com when you are Partner with Silver or Gold competency level to get technical advice - or contact your SAM (Service account manager) when you have an ASfP contract to raise a cloud consult. Then a Partner Consultant can work with you on how to do management in the respective scenarios. 

 

Also there were quite a lot updates in the documentation in the meantime, so I generally recommend to take a look (Don't know if it solves any of the specific issues you see though):

https://docs.microsoft.com/en-us/partner-center/develop/enable-secure-app-model and updates to the powershell modules: 

https://docs.microsoft.com/en-us/powershell/partnercenter/multi-factor-auth?view=partnercenterps-2.0 

 

Also Isaiah Williams has published a few more more lab-oriented guides on his blog in the same: https://docs.isaiahwilliams.dev/articles/partner-security-requirements.html

Kind regards, Janosch (Note: Leaving role as of March 2023, don't expect further answers. Connect with me via LinkedIn: https://linkedin.com/in/janoschulmer)
Mihai
Microsoft

Hi @idwilliams 

 

Thank you for adding your input above!

 

There is a different way to solve this problem? Or at least could you please direct us to someone who can provide a solution on this matter?

 

Thank you!

Mihai