Search code examples
c#azureoauth-2.0azure-active-directoryazure-application-proxy

Accessing On Premise Api Through Azure Proxy with Azure Directory Enabled


I'm attempting to expose my on-premise APIs with Azure Application Proxy.

I've successfully configured it to work with the Pre-Authentication set to Passthrough. When I change the Pre-Authentication to Azure Active Directory I can access the endpoint successfully via a browser. However, when I try calling the on-premise endpoint from code I receive the HTML for the Microsoft Sign-In page. A successful request will return a JSON Response.

I'm following a Microsoft article: Secure access to on-premise APIs with Azure AD Application Proxy

Via an Azure Docs defect, I learned that I have to use "http://localhost" as a value for the RedirectUri and configure my client app as a "Mobile and desktop applications" platform.

Here is my code:

[Fact]
public async Task Successfully_authenticate_but_cant_access_the_proxy()
{
    // Acquire Access Token from AAD for Proxy Application
    var clientApp = PublicClientApplicationBuilder
        .Create("b510069b-xxxx-xxxx-xxxx-9363xxxxxxxx") //Client Id for Client Application
        .WithRedirectUri("http://localhost") // This must be configured as a "Mobile and desktop applications" platform in the client application
        .WithTenantId("xxxxxx-d4cf-4xxx-xxxx-8dc72cbc00bd") //Not sure if this is needed.
        .WithAuthority("https://login.microsoftonline.com/xxxxxx-d4cf-4xxx-xxxx-8dc72cbc00bd")
        .Build();

    AuthenticationResult authResult;
    var accounts = await clientApp.GetAccountsAsync();
    var account = accounts.FirstOrDefault();

    IEnumerable<string> scopes = new string[] {"https://endpoints-xxx.msappproxy.net/user_impersonation"};

    try
    {
        authResult = await clientApp.AcquireTokenSilent(scopes, account).ExecuteAsync();
    }
    catch (MsalUiRequiredException ex)
    {
        authResult = await clientApp.AcquireTokenInteractive(scopes).ExecuteAsync();                
    }

    if (authResult != null)
    {
        //Use the Access Token to access the Proxy Application
        var httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        var response = await httpClient.GetAsync("https://endpoints-xxx.msappproxy.net");

        //Failing here. I'm receiving the HTML for the Sign-In page. I'm expecting a response with JSON.
        var responseValue = await response.Content.ReadAsStringAsync();
    }
}

Has anyone had any success accessing an on-premise endpoint via Azure Application Proxy with Azure Active Directory?


Solution

  • I opened a ticket with Microsoft and they were able to identify the issue.

    The scopes needed a second slash '/' after the domain name:

    IEnumerable<string> scopes = new string[] {"https://endpoints-xxx.msappproxy.net//user_impersonation"};
    

    The complete code looks like this:

    [Fact]
    public async Task Successfully_authenticate_but_cant_access_the_proxy()
    {
        // Acquire Access Token from AAD for Proxy Application
        var clientApp = PublicClientApplicationBuilder
            .Create("b510069b-xxxx-xxxx-xxxx-9363xxxxxxxx") //Client Id for Client Application
            .WithRedirectUri("http://localhost") // This must be configured as a "Mobile and desktop applications" platform in the client application
            .WithTenantId("xxxxxx-d4cf-4xxx-xxxx-8dc72cbc00bd") //Not sure if this is needed.
            .WithAuthority("https://login.microsoftonline.com/xxxxxx-d4cf-4xxx-xxxx-8dc72cbc00bd")
            .Build();
    
        AuthenticationResult authResult;
        var accounts = await clientApp.GetAccountsAsync();
        var account = accounts.FirstOrDefault();
    
        IEnumerable<string> scopes = new string[] {"https://endpoints-xxx.msappproxy.net//user_impersonation"};
    
        try
        {
            authResult = await clientApp.AcquireTokenSilent(scopes, account).ExecuteAsync();
        }
        catch (MsalUiRequiredException ex)
        {
            authResult = await clientApp.AcquireTokenInteractive(scopes).ExecuteAsync();                
        }
    
        if (authResult != null)
        {
            //Use the Access Token to access the Proxy Application
            var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
            var response = await httpClient.GetAsync("https://endpoints-xxx.msappproxy.net");
    
            //Failing here. I'm receiving the HTML for the Sign-In page. I'm expecting a response with JSON.
            var responseValue = await response.Content.ReadAsStringAsync();
        }
    }