我试图在C#应用程序上运行某些Powershell脚本以授予Azure AD App的权限,但它在Powershell上有效,但在C#应用程序上却不起作用

时间:2019-01-04 08:35:49

标签: c# azure powershell azure-active-directory

我正在尝试使用c#应用程序中的Powershell命令授予对Azure Active Directory应用程序的权限。 首先,我尝试在Powershell中使用以下脚本。

Runspace runspace2 = RunspaceFactory.CreateRunspace();
        runspace2.Open();
        Pipeline pl = runspace2.CreatePipeline();
        pl.Commands.AddScript("Function Grant-OAuth2PermissionsToApp{ \n" +
            "$azureAppId = '" + appID + "'; \n" +
            "$username = '<login id >'; \n" +
            "$password = convertTo-securestring '<password>' -AsPlainText -Force; \n" +
            "$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password; \n" +
            "$res = login-azurermaccount -Credential $cred; \n" +
            "$context = Get-AzureRmContext; \n" +
            "$tenantId = $context.Tenant.Id; \n" +
            "$refreshToken = @($context.TokenCache.ReadItems() | where {$_.tenantId -eq $tenantId -and $_.ExpiresOn -gt (Get-Date)})[0].RefreshToken; \n" +
            "$body = 'grant_type=refresh_token&refresh_token=$($refreshToken)&resource=\"74658136-14ec-4630-ad9b-26e160ff0fc6\"'; \n" +
            "$apiToken = Invoke-RestMethod 'https://login.windows.net/$tenantId/oauth2/authorize?client_id=$azureAppId&response_type=code&&redirect_uri=https%3A%2F%2FPowerBiApp.contoso.com&response_mode=query' -Method POST -Body $body -ContentType 'application/x-www-form-urlencoded'; \n" +
            "$header = @{ \n" +
            "'Authorization'='Bearer '+$apiToken.access_token; \n" +
            "'X-Requested-With'='XMLHttpRequest'; \n" +
            "'x-ms-client-request-id'=[guid]::NewGuid(); \n" +
            "'x-ms-correlation-id'=[guid]::NewGuid(); \n" +
            "}; \n" +
            "$url = 'https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$azureAppId/Consent?onBehalfOfAll=true'; \n" +
            "Invoke-RestMethod -Uri $url -Headers $header -Method POST -ErrorAction Stop; \n" +
            "}");
        pl.Commands.AddScript("Grant-OAuth2PermissionsToApp");
        var r = pl.Invoke();

此代码授予了Azure AD注册应用程序的权限。 我修改了此脚本以在C#应用程序中运行它。

$refreshToken

这给了我解析错误-刷新令牌格式错误或无效。 我尝试了以下方法来获得解决方案:

    在获得$refreshtoken = $refreshtoken.Split(''n')[0];的值后,在代码中使用
  1. 尝试拆分字符串,以便如果我两次获得令牌字符串,则只能选择一个。

    -AsPlainText

  2. 我发现在https://login.microsoftonline.com/{tenant}/oauth2/authorize?client_id=<ApplicationId>&response_type=code&&redirect_uri=<Application redirect Url>&response_mode=query之类的Powershell脚本中使用的“-”可能会更改为endash。我重新检查了脚本中使用的所有“-”。

  3. 另一个解决方案是我发现,当我们尝试使用原始数据获取刷新令牌时,应使用以下url和参数。我从site

    获得此网址

    {{1}}

这些我尝试过的所有方法都无效。 是否有解决此问题的适当方法? 还是还有其他方法可以获取RefreshToken来授予权限?

1 个答案:

答案 0 :(得分:1)

我认为根本原因是由于某些Powershell脚本未正确转换为C#代码。

我在c#代码中设置了一个断点,并获取了生成的powershell脚本,然后将其与原始的powershell脚本进行比较。 c#中的某些脚本用单引号括起来,但是在原始的Powershell中,它用双引号括起来,这可能会导致一些错误。

例如,在原始的Powershell中,以下代码行:$body = "grant_type=refresh_token&refresh_token=$($refreshToken)&resource=74658136-14ec-4630-ad9b-26e160ff0fc6",但是在您的c#代码中(设置断点以获取值),它用单引号括起来,例如$body ='grant_type=refresh_token&refresh_token=$($refreshToken)&resource="74658136-14ec-4630-ad9b-26e160ff0fc6"'

因此,请在您的c#代码处设置一个断点,并从c#中获取生成的powershell脚本,并确保它与原始的powershell脚本相同。

根据比较,您的c#代码中需要更改3行,您可以将相应的行替换为以下行:

"$body = \"grant_type=refresh_token&refresh_token=$($refreshToken)&resource=74658136-14ec-4630-ad9b-26e160ff0fc6\"; \n" +

"$apiToken = Invoke-RestMethod \"https://login.windows.net/$tenantId/oauth2/authorize?client_id=$azureAppId&response_type=code&&redirect_uri=https%3A%2F%2FPowerBiApp.contoso.com&response_mode=query\" -Method POST -Body $body -ContentType 'application/x-www-form-urlencoded'; \n" +

"$url = \"https://main.iam.ad.ext.azure.com/api/RegisteredApplications/$azureAppId/Consent?onBehalfOfAll=true\"; \n" +

希望有帮助。

从c#代码获取生成的ps脚本:

enter image description here