Azure APIM: Send a client certificate with send-request mode - azure

Is it possible in azure apim to use the policy "send-request mode" to send a certificate with the request?
<send-request mode="new" response-variable-name="" timeout="seconds" ignore-error="true">
<set-url></set-url>
<set-method>GET</set-method>
<set-header name="" exists-action="override">
<value></value>
</set-header>
<set-body></set-body>
</send-request>

Is it possible in azure apim to use the policy "send-request mode" to send a certificate with the request?
In short, it's possible.
The send-request policy sends the provided request to the specified URL, waiting no longer than the set timeout value.
Policy statement is as below:
<send-request mode="new|copy" response-variable-name="" timeout="60 sec" ignore-error
="false|true">
<set-url>...</set-url>
<set-method>...</set-method>
<set-header name="" exists-action="override|skip|append|delete">...</set-header>
<set-body>...</set-body>
<authentication-certificate thumbprint="thumbprint" />
</send-request>
Use the authentication-certificate policy to authenticate with a backend service using client certificate. The certificate needs to be installed into API Management first and is identified by its thumbprint.

Related

Azure APIM with certificate authentication error using .pfx certificate

Helle, everyone.
I am experiencing issue with configuring APIm operation with InBound policy, which handled calls to remote endpoint. I have saved certificate which was provided to me by external service and using thumbprint in policie. Remote endpoint validates requests using certificate.
<policies>
<inbound>
<base />
<send-request mode="new" response-variable-name="result" timeout="300" ignore-error="false">
<set-url>https://ip:port/path</set-url>
<set-method>POST</set-method>
<set-header name="Accept" exists-action="override">
<value>*/*</value>
</set-header>
<set-header name="Content-Type" exists-action="override">
<value>application/xml</value>
</set-header>
<set-body>#(context.Request.Body.As<string>())</set-body>
<authentication-certificate thumbprint="thubprint" password="password" />
</send-request>
<return-response response-variable-name="result" />
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
But as a response I am getting 500 error
send-request (259.918 ms)
{
"messages": [
"Error occured while calling backend service.",
"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.",
"The remote certificate is invalid according to the validation procedure."
]
}
Thanks beforehands. Would appreciate any help.
As discussed in the comments, adding gist as a community wiki answer to help community members who might face a similar issue.
But as a response I am getting 500 error
If you are using self-signed certificates, you will need to disable certificate chain validation for API Management to communicate with the backend system. Otherwise, it will return a 500 error code.
Try the following code snippet taken from the document:
$context = New-AzApiManagementContext -resourcegroup 'ContosoResourceGroup' -servicename 'ContosoAPIMService'
New-AzApiManagementBackend -Context $context -Url 'https://contoso.com/myapi' -Protocol http -SkipCertificateChainValidation $true
Note: As of now disabling certificate chain validation is only possible for backend policy.
You can refer to Azure API Management - Validate incoming client certificate and Send cert to backend, Is disabling Validate certificate chain safe? and Protect your APIs with Azure API Management

Checking correctness of traceparent http header in Azure API Management

Is there a way to check correctness of traceparent http header using Azure API Management policies before is forwarded to backend service?
The best that I could find is to create API management policy with regular expression. It will find most of invalid cases, expect some of corner cases. If invalid http traceparent header supplied then 400 - bad request, response is returned.
<choose>
<when condition="#(!Regex.IsMatch(context.Request.Headers.GetValueOrDefault("traceparent",""), #"^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(500)))">
<return-response>
<set-status code="400" reason="Bad request - Missing or invalid traceparent http header" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>#(new JObject(new JProperty("statusCode", 400), new JProperty("message", "Missing or invalid &apos;traceparent&apos; http header for distributed tracing. More information how to supply one at https://www.w3.org/TR/trace-context-1/")).ToString())</set-body>
</return-response>
</when>
</choose>
Only manually. You can use choose policy with a policy expression where you get value of the header and validate it using C# code. And then take different actions depending on whether you deem it valid or not.

Handle JWT Token validation failute in Azure API Management Service

Hi I have added the jwt validate tag to one of the operation in my api management service as shown below
<!-- validate the bearerToken !-->
<validate-jwt header-name="Authorization" output-token-variable-name="jwtOutput">
<openid-config url="{{OPENIDConfigURL}}" />
<issuers>
<issuer>{{tokenIssuer}}</issuer>
</issuers>
</validate-jwt>
while testing the same with invalid JWT token I am getting internal server error but its not getting captured in my tag. Am i missing something here.
<on-error>
<base />
<return-response>
<set-status code="200" />
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>{
{{FailResponse}};
}</set-body>
</return-response>
</on-error>
Any leads on how to capture the error when the provided jwt token is invalid (for any reason)
I believe you're getting an internal server error because your policy on-error is invalid.
Have a look to this thread and adjust your policy on-error. You can basically use the sample they have available in that link. The errors list shows you the list of errors you can expect from the validate-jwt policy.

Validating Authorization token in incoming requests with Azure API management and third party Authorization Server

I have to implement OAuth 2.0 in my project with a third party Authorization Server. Both my client and server are already registered on the AS. I have created an API management instance on Azure and imported the swagger APIs. I want every incoming request to be validated against my AS, so I just need to redirect the request to https://my-as.com/as/introspect.oauth2, and have the token validated. If the token is valid then let it proceed or else send 401. I was trying to implement this using "inbound processing" and referred to the following doc: https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-protect-backend-with-aad#configure-a-jwt-validation-policy-to-pre-authorize-requests.
The only problem is that instead of Azure AD I'm using a third party AS. I tried replacing the URL in sample XML code with my URL, but its not working.
How do I redirect requests to the Authorization Server for validating access token?
Adding following inbound policy worked:
<inbound>
<!-- Extract Token from Authorization header parameter -->
<set-variable name="token" value="#(context.Request.Headers.GetValueOrDefault("Authorization","scheme param").Split(' ').Last())" />
<!-- Send request to Token Server to validate token (see RFC 7662) -->
<send-request mode="new" response-variable-name="tokenstate" timeout="20" ignore-error="true">
<set-url>https://my-as.com/as/introspect.oauth2</set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/x-www-form-urlencoded</value>
</set-header>
<set-body>#($"grant_type=urn:pingidentity.com:oauth2:grant_type:validate_bearer&client_id=UoM&client_secret=somesecret&token={(string)context.Variables["token"]}")</set-body>
</send-request>
<choose>
<!-- Check active property in response -->
<when condition="#((bool)((IResponse)context.Variables["tokenstate"]).Body.As<JObject>()["active"] == false)">
<!-- Return 401 Unauthorized with http-problem payload -->
<return-response response-variable-name="existing response variable">
<set-status code="401" reason="Unauthorized" />
<set-header name="WWW-Authenticate" exists-action="override">
<value>Bearer error="invalid_token"</value>
</set-header>
</return-response>
</when>
</choose>
<base />
</inbound>

Redirect policy in Azure API Management

Does Azure API Management (Azure APIM) provide any way to redirect urls, in order to replicate Apigee RedirectToLoginPage functionality
You can do it with a policy set at the global (All APIs) scope.
<choose>
<when condition="#(!context.Request.OriginalUrl.Host.Contains("redirect.com"))">
<return-response>
<set-status code="303" reason="See Other" />
<set-header name="Location" exists-action="override">
<value>#("https://redirect.com/" + context.Request.OriginalUrl.Path + context.Request.OriginalUrl.QueryString)</value>
</set-header>
</return-response>
</when>
</choose>
At the time of writing this isn't supported at Azure APIM level. Since I was using IdentityServer for Oauth2 security, I accomplished this by writing an owin/katana authentication middleware. Anders Abel has a great post about it.

Resources