Azure API Management - Authentication using HTTP query parameters - azure-api-management

I want to expose an API that uses HTTP query parameters for authentication. Something like this:
{root-backendURL}/resource?login=loginName&password=loginPassword
I am using Azure API Management. I've created a new API which points to the backend service, and I've created a new operation called "Resource". For that operation I've added two Query parameters that are required.
Now I want to expose and make use of the APIM Gateway URL that should look something like this:
{root-GatewayURL}/apiName/resource
Adding those two required query parameters will make the URL look like this:
{root-GatewayURL}/apiName/resource?login=loginName&password=loginPassword
When I test the Gateway URL using Postman, I get a 401 response.
{
"code": 401,
"errors": [
{
"message": "Authentication failed."
}
]
}
I've tried to use a Send-Request policy and add from there the query parameters. This way it works.
<rewrite-uri template="/" />
<set-variable name="login" value="loginName" />
<set-variable name="password" value="loginPassword" />
<send-request mode="new" response-variable-name="resource" ignore-error="false">
<set-url>#($"{root-BackendURL}/resource?login={(string)context.Variables["login"]}&password={(string)context.Variables["password"]}")</set-url>
<set-method>GET</set-method>
</send-request>
<return-response>
<set-body>#(new JObject(new JProperty("resource",((IResponse)context.Variables["resource"]).Body.As<JObject>())).ToString())</set-body>
</return-response>
I've double checked the URLs and they are identical. Why do I get different results?
I do not want to use the policy, I want to make it work using the query parameters, because I need to use also an ID for the resource and also other query parameters, for example:
{root}/resource/{id}?limit=25&offset=50&loginName&password=loginPassword

Related

How to perform a 302 Redirect with a forwarding URL

We are using Xamarin and UITest in order to create UI tests for our application.
We are using Azure API management for integration, and am trying to mock our Authentication process.
We are using Xamarin Essentials WebAuthenticator, which opens an external browser in order to do the two step OAuth and load a login page.
Since UITest cannot control anything outside of the app itself, we need to have API management respond by giving a 302 redirect back to the controlling app, with our test authentication tokens that are mocked.
I've tried creating a mock response that returns a 302, with a Location header with the value of our return url for the app. However whenever I test this in the APIM test page, it simply just returns a 200 OK.
Is it possible to make a GET request to APIM, which performs a 302 redirect to a specified uri, with a body of mocked test data?
You may try with a return-response policy.
Something similar to this example:
<when condition="#(context.Request.OriginalUrl.Scheme == Uri.UriSchemeHttp)">
<return-response>
<set-status code="302" reason="Temporary Redirect" />
<set-header name="Location" exists-action="override">
<value>#{
var uri = context.Request.OriginalUrl;
return Uri.UriSchemeHttps + "://" + uri.Host + uri.Path + uri.QueryString;
}</value>
</set-header>
</return-response>
</when>
For your reference: https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#ReturnResponse

Azure API Management - Can I define a custom response status code?

When setting up the all the possible response codes and their descriptions for an endpoint in API Management Service, I can only choose an existing status code from a dropdown list, but it doesn't allow me to add a custom status code, such as 499. I use the 499 status code in my API for a specific type of error relevant to my applicatoin. Is there any way to add this to the list of responses?
You could dynamic mocking using APIM with an APIM policy called return-response.
<return-response>
<set-status code="200" reason="OK" />
<set-header name="content-type" exists-action="override">
<value>"application/json"</value>
</set-header>
<set-body>{
"id": "cat12345",
"name": "Garfield",
"tag": "Sleepy Cat"
}</set-body>
</return-response>
For more details, you could refer to this tutorial.
Not with forms UI. But if you select an API, there'll be a pencil in Frontend block on Design tab. It allows you to edit your API specification in OpenAPI 2/3 spec. Using that it should be possible to add a custom response statuses code.

Parameterize Azure API Management backend

I am trying to do something like this:
<set-backend-service base-url="https://{{context.Variables['instance']}}/api" />
Or
<set-backend-service backend-id="my-{{context.Variables['instance']}}-api"/>
But getting errors that I've given an invalid URL or that APIM can't locate that backend. Is there a way to parameterize your backend?
The way you are trying is only applicable in liquid templates when using the set-body policy OR when using Named Values. In other scenarios, it has to be a policy expression.
Something like this can be done instead
<set-variable name="resource-group-name" value="rg-01" />
<set-variable name="logic-app-name" value="la-01" />
<set-backend-service id="apim-generated-policy" backend-id="#("LogicApp_" + context.Variables["resource-group-name"] + "_" + context.Variables["logic-app-name"])" />
PS: The example above is for a Logic App backend created when importing one from the Portal UI.

How can I create API with my custom code in Azure?

Can I create an API that has the definition of the sum of two numbers and returns me the output. I want to write all the logic in Azure Web API Management itself. Is there any provision, or do I need to create it in my machine and import it to Azure Web API Management?
Is it possible to create it in Web API in Azure itself, rather than importing it?
There are two ways to go about this. APIM does support policy expressions: https://learn.microsoft.com/en-us/azure/api-management/api-management-policy-expressions This allows you to plug in arbitrary code into request processing pipeline. You can check policy samples here: https://learn.microsoft.com/en-us/azure/api-management/policy-samples to see this in action. When combined with other policies it does allow you to a lot of things. If we assume that you "addition" operation has URI template of /add?a={a}&b={b} then you can sum up and return result with one simple policy:
<return-response>
<set-status code="200" reason="OK" />
<set-body>#{
var a = int.Parse(context.Request.Url.Query.GetValueOrDefault("a", "0"));
var b = int.Parse(context.Request.Url.Query.GetValueOrDefault("b", "0"));
return (a + b).ToString();
}</set-body>
</return-response>
As you can see this is a pretty much regular C# code, but it's limited in what you can do and what types you can use (see first link). If you can't make it work within these limitations your best bet is to move custom logic outside of APIM, into Azure Functions, for example.

coldfusion - receiving posted JSON data and parsing it

This is the first time I'm writing a cfc that will catch JSON data from an external web server that would be posting information.
I'm working with a new service that can be set to send us, via HTTP POST to a URL I specify, a JSON packet of information regarding failed transactions.
I figured I'd setup a CFC with remote access to capture and deserialize the JSON data into something we could then act on. However, I can't figure out how to setup the function in the CFC to received the data?
I set the URL to www.mydomain.com/com/processRemote.cfc?method=catchJSONdata&ReturnFormat=json
To test it, I setup a simple test page that should post session data:
<cfhttp
result="result"
method="post"
url="http://www.mydomain.com/com/processRemote.cfc?method=catchJSONdata&ReturnFormat=json">
<cfhttpparam type="header" name="content-type" value="application/json"/>
<cfhttpparam type="body" value="#serializeJSON(session)#"/>
So where I'm lost is what's the cfargument name that I'd have in my cfc that I would initially store the JSON data in? I have no control over the remote service that would be sending the JSON data.
Thanks,
If you're reading content from the HTTP request body you wont find it in arguments scope - you'll need to extract it directly from the request:
if (cgi.content_type EQ "application/json")
{
myData = deserializeJSON(ToString(getHTTPRequestData().content));
}
I use the Taffy[1] framework for building services like this (Disclaimer: I actually helped write the part of the framework that handles this case).
[1] http://atuttle.github.com/Taffy/