microsoft / azure-container-apps

Roadmap and issues for Azure Container Apps
MIT License
362 stars 29 forks source link

EasyAuth /.auth/me endpoint returns 404 #479

Open tkmhp opened 1 year ago

tkmhp commented 1 year ago

Please provide us with the following information:

This issue is a: (mark with an x)

Issue description

After enabling Authentication with Azure AD it's not possible to retrieve tokens via /.auth/me endpoint. It seems that the TokenStore is completely missing in this feature.

Steps to reproduce

  1. Enable Authentication for Azure AD
  2. Log in to deployed application
  3. Open /.auth/me

Expected behavior [What you expected to happen.] Receive token information in the same way like with App Service.

Actual behavior [What actually happened.] 404

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context

Ex. Did this issue occur in the CLI or the Portal? In Portal there is no option to enable TokenStore. CLI documentation has this option (az containerapps auth update --enable-token-store) but it doesn't work. The debug output shows that the request contains correct structure for enabling tokenstore ( login: { tokenStore: { enabled: true }} ), but the output just trims this part.

dariagrigoriu commented 1 year ago

tokenStore is not currently supported.

tkmhp commented 1 year ago

Thanks for reaching me out. In this case docs are wrong/misleading as it states: "These tokens are sent by the provider and stored in the EasyAuth token store." here: https://learn.microsoft.com/en-us/azure/container-apps/authentication-azure-active-directory#-enable-azure-active-directory-in-your-container-app.

adammerk commented 1 year ago

tokenStore is not currently supported.

If the tokenStore is not supported why is a "enable token store" parameter mentioned in "az containerapp auth update" command.

az containerapp auth update --name --resource-group [--action {AllowAnonymous, RedirectToLoginPage, Return401, Return403}] [--config-file-path] [--custom-host-header] [--custom-proto-header] [--enable-token-store {false, true}] [--enabled {false, true}] [--excluded-paths] [--proxy-convention {Custom, NoProxy, Standard}] [--redirect-provider] [--require-https {false, true}] [--runtime-version] [--set]

See: https://learn.microsoft.com/en-us/cli/azure/containerapp/auth?view=azure-cli-latest#az-containerapp-auth-update

Thanks for having a look!

subesokun commented 1 year ago

Stumbled on this issue while trying to figure out how to retrieve the access token which should be stored in the token store (see https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-oauth-tokens#retrieve-tokens-in-app-code). However, I don't receive any of the mentioned headers like X-MS-TOKEN-AAD-ACCESS-TOKEN but only a X-MS-CLIENT-PRINCIPAL token which containers not a valid Access Token (maybe Identity Token?). Also the .auth/me endpoint is missing as already mentioned in this issue.

@dariagrigoriu Do you know if it's possible to retrieve the proper Access Token (e.g. for accessing the Graph API on the user's behalf) on the server via the headers?

davihern commented 1 year ago

Is there any way to retrieve the access token? (e.g. /.auth/me) Is this feature in the roadmap?

PeterAronZentai commented 1 year ago

This is a key element for basic uses cases and a possible blocker for migrating typical EasyAuth enabled App Service apps. Any plans to resolve this?

Wompipomp commented 1 year ago

Same here. Backstage has an EasyAuth provider which needs token store to work properly on ACA

johnnyreilly commented 10 months ago

It's possible that https://github.com/microsoft/azure-container-apps/issues/995 is a duplicate of this thread. Not sure - but it certainly has overlap. Let me copy over things that seem relevant to that here in the hope that it helps.

I'm a long time user of Easy Auth and was delighted when it landed in ACAs. I uncovered an issue early on around how to get .NET to recognise the X-MS-CLIENT-PRINCIPAL header that is supplied with Easy Auth and wrote up a workaround: https://johnnyreilly.com/azure-container-apps-easy-auth-and-dotnet-authentication

This has served me well, however I'm now trying to make use of the Graph API on behalf of my logged in user. I cannot.

Reading the docs I believe I should be trying to use the "on behalf of" approach:

var scopes = new[] { "https://graph.microsoft.com/.default" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";

// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";

// using Azure.Identity;
var options = new OnBehalfOfCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
};

// This is the incoming token to exchange using on-behalf-of flow
var oboToken = "JWT_TOKEN_TO_EXCHANGE";

var onBehalfOfCredential = new OnBehalfOfCredential(
    tenantId, clientId, clientSecret, oboToken, options);

var graphClient = new GraphServiceClient(onBehalfOfCredential, scopes);

The problem is, there's not JWT token that we can make use of in the headers. This is supported in App Service which has a token store and supports the following headers:

X-MS-TOKEN-AAD-ID-TOKEN
X-MS-TOKEN-AAD-ACCESS-TOKEN
X-MS-TOKEN-AAD-EXPIRES-ON
X-MS-TOKEN-AAD-REFRESH-TOKEN

If there was a populated X-MS-TOKEN-AAD-ACCESS-TOKEN then using the "on behalf of" approach above would work. As there are not such headers in Easy Auth with Azure Container Apps, this is not possible. To be clear X-MS-CLIENT-PRINCIPAL is not a JWT - it's a base 64 encoded JSON representation of the principal.

There's definitely some overlap between this issue and https://github.com/microsoft/azure-container-apps/issues/479 - it's not clear to me that they are exactly the same issue though; so I've raised this instead. I'll copy the content across to the other in case this a dupe in which case this can be closed.

Steps to reproduce

Add a controller to your app to surface headers:

    [HttpGet("api/headers")]
    public async Task<IActionResult> GetHeaders()
    {
        var headers = new Dictionary<string, string>();
        foreach (var header in Request.Headers) {
            if (headers.Keys.Contains(header.Key))
            {
                headers[header.Key] = header.Value.FirstOrDefault() ?? "";
            }
            else
            {
                headers.Add(header.Key, header.Value.FirstOrDefault() ?? "");
            }
        }
        return Ok(headers);
    }

Take a look at what comes out.

Expected behavior [What you expected to happen.]

Going to /api/headers surfaces headers which include the following:

X-MS-TOKEN-AAD-ID-TOKEN
X-MS-TOKEN-AAD-ACCESS-TOKEN
X-MS-TOKEN-AAD-EXPIRES-ON
X-MS-TOKEN-AAD-REFRESH-TOKEN

i.e. JWT tokens in headers that can be consumed and used.

Actual behavior [What actually happened.]

Headers do not include the hoped for tokens. These are the headers I encountered:

[
    "Accept",
    "Host",
    "User-Agent",
    "Accept-Encoding",
    "Accept-Language",
    "Cookie",
    "traceparent",
    "Upgrade-Insecure-Requests",
    "Content-Length",
    "sec-ch-ua",
    "sec-ch-ua-mobile",
    "sec-ch-ua-platform",
    "DNT",
    "sec-fetch-site",
    "sec-fetch-mode",
    "sec-fetch-user",
    "sec-fetch-dest",
    "x-forwarded-for",
    "x-envoy-external-address",
    "X-Request-ID",
    "x-envoy-expected-rq-timeout-ms",
    "x-k8se-app-name",
    "x-k8se-app-namespace",
    "x-k8se-protocol",
    "x-k8se-app-kind",
    "x-ms-containerapp-name",
    "x-ms-containerapp-revision-name",
    "x-arr-ssl",
    "x-forwarded-proto",
    "X-MS-CLIENT-PRINCIPAL-NAME",
    "X-MS-CLIENT-PRINCIPAL-ID",
    "X-MS-CLIENT-PRINCIPAL-IDP",
    "X-MS-CLIENT-PRINCIPAL"
]
matt-erhart commented 1 month ago

Is this resolved by: https://learn.microsoft.com/en-us/azure/container-apps/token-store?

PeterAronZentai commented 1 month ago

It is. it works now. you'll need some tweaks if you need extra permissions beyond basic profile read.