<!--
    // ====================================================================================================
    // Extract encrypted access token from cookie to call downstream API
    // Values in {{value}} syntax are defined as Named Values in APIM instance.
    // ====================================================================================================
-->
<policies>
    <inbound>
        <base />
        <cors allow-credentials="true">
            <allowed-origins>
                <origin>{{return-uri}}</origin>
            </allowed-origins>
            <allowed-methods preflight-result-max-age="300">
                <method>*</method>
            </allowed-methods>
            <allowed-headers>
                <header>*</header>
            </allowed-headers>
            <expose-headers>
                <header>*</header>
            </expose-headers>
        </cors>
        <!-- 
            // ====================================================================================================
            // 1. Extract cookies from the request header.
            // 2. Split all cookies and select the one we're interested in.
            // 3. Remove cookie name to leave only the contents.
            // 4. Decode the cookie content from base64url to base64.
            // 5. Decode the base64 cookie content to bytes.
            // 6. Extract the IV from the encrypted cookie content.
            // 7. Decrypt the encrypted cookie content into a variable.
            // ====================================================================================================
         -->
        <set-variable name="access_token" value="@{
            try {
                string cookie = context.Request.Headers
                                            .GetValueOrDefault("Cookie")?
                                            .Split(';')
                                            .ToList()?
                                            .Where(p => p.Contains("{{cookie-name}}"))
                                            .FirstOrDefault()
                                            .Replace("{{cookie-name}}=", "");
                byte[] encryptedBytes = Convert.FromBase64String(System.Net.WebUtility.UrlDecode(cookie));
                byte[] iv = new byte[16];
                byte[] tokenBytes = new byte[encryptedBytes.Length - 16];
                Array.Copy(encryptedBytes, 0, iv, 0, 16);
                Array.Copy(encryptedBytes, 16, tokenBytes, 0, encryptedBytes.Length - 16);
                byte[] decryptedBytes = tokenBytes.Decrypt("Aes", Convert.FromBase64String("{{enc-key}}"), iv);
                char[] convertedBytesToChar = Encoding.UTF8.GetString(decryptedBytes).ToCharArray();
                return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(convertedBytesToChar));
            } catch (Exception ex) {
                return null;
            }
        }" />
        <!-- 
            // ====================================================================================================
            // Set the decrypted access token as an Authorization header.
            // ====================================================================================================
         -->
        <choose>
            <when condition="@(!string.IsNullOrEmpty(context.Variables.GetValueOrDefault<string>("access_token")))">
                <set-header name="Authorization" exists-action="override">
                    <value>@($"Bearer {context.Variables.GetValueOrDefault<string>("access_token")}")</value>
                </set-header>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <choose>
            <when condition="@(string.IsNullOrEmpty(context.Variables.GetValueOrDefault<string>("access_token")))">
                <return-response>
                    <set-status code="401" reason="Unauthorized" />
                </return-response>
            </when>
        </choose>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>