We are in the process of totally rewriting our main API Proxy config and we discovered an issue with our new configuration (or maybe our existing one) relating to how API keys are being validated. Our current API uses the policy GetOAuthV1Info
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<GetOAuthV1Info enabled="true" continueOnError="false" async="false" name="APIKey-Validate">
<DisplayName>APIKey-Validate</DisplayName>
<FaultRules/>
<Properties/>
<AppKey ref="request.queryparam.apikey"></AppKey>
</GetOAuthV1Info>
Our new configuration uses the policy VerifyAPIKey
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-Api-Key">
<DisplayName>Verify API Key</DisplayName>
<APIKey ref="request.queryparam.apikey"/>
</VerifyAPIKey>
On the surface both of these policies appear to work fine. However, after deploying the new config to our test environment some API keys were failing with a 401 Unauthorized error. Digging into those keys we discovered that they are assigned to a product that doesn't have access to the test environment. It appears that the GetOAuthV1Info step is not validating the environment..? The documentation for GetOAuthV1Info doesn't help as it doesn't talk about APIKeys at all (http://apigee.com/docs/api-services/content/authorize-requests-using-oauth-10a).
Fixing this particular issue is pretty straight forward in that we just need to allow those other products access to the test environment. However, this makes me wonder what the other differences are between these two policies? I'm very nervous now about deploying any changes to these API proxies because I don't know what else will break, or what other unforeseen issues will appear.
Is this a known limitation with the GetOAuthV1Info policy? Why does this even work at all? What are the other differences between these two policies that might bite me later?
The only difference that I'm aware of is that the variable names are assigned differently in the VerifyAPIKey Policy (it appends the policy type and name to the vairalbes like verifyapikey.verify_apikey-1.apiproduct.developer.quota.limit for example).
Both VerifyAPIKey and OAuth 1 does support restrictions by environment -- when I tested the GetOAuthV1 with an APIKey in an invalid environment and got this error:
OAuth Failure : Invalid API call as no apiproduct match found
Keep in mind that the convention for most projects seems to be either OAuth2 flows or the VerifyAPI so there is less information about the OAuth1 policies.
Related
I have a service that has references to other services with some of them being references to different environments of the same service (e.g. prod/test).
I am using the #if precompile directive to include different versions of these references with the using statement. Example:
#if Debug
using ServiceTest
#else
using ServiceProd
#endif
In the Web.config file I have two child nodes inside the <client> node. Example:
<client>
<endpoint address="http://test.domain.com/Service"
binding="basicHttpBinding" bindingConfiguration="Service"
contract="ServiceTest" name="Service" />
<endpoint address="http://prod.domain.com/Service"
binding="basicHttpBinding" bindingConfiguration="Service"
contract="ServiceProd" name="Service" />
</client>
Is the above part of the Web.config valid or not? More precisely, can there be any side-effects because of having two endpoints with the same name and binding configurations? The main concern is having a wrong endpoint called (e.g. calling prod endpoint instead of test or the other way around).
Any guidance and advice regarding the above will be really appreciated.
Is the above part of the Web.config valid or not?
Every time when you run your application CLR reads web.config file and deserialize it as an object. To deserialize XML it's uses classes declaration in "configSections" section of your config file.
So, the answer "valid or not" depends on implementation of "client" configuration section. I believe this should be part of your application or code from nuget library. This is why we can't answer you with confidence.
More precisely, can there be any side-effects because of having two endpoints with the same name and binding configurations?
Frankly, I don't understand how this should work. In what manner 3rd library should know that it needs to load first but not second client endpoint?
Possible solutions.
You can use web.config transformation. There are tons of resources about this feature of .NET Framework.
The simplest scenario would be to substitute endpoint address keeping the same endpoint name.
Another common scenario is to give different endpoint names and keep "alive" endpoint name in AppSettings. In this case your code should resolve endpoint name first and then actual endpoint address.
In our environment we have both a primary and contingency server to ensure some continuity of operations in the event one site goes down. During testing of the contingency server we discovered a Flex based application will not allow users to login and returns a "Auth error: send failed". When monitoring network activity I see the following:
It looks to me like the cross domain policy is causing the issue as I do not see anything similar when I load the Flex application in our primary environment.
Here is the contents of the crossdomain.xml file found in our web root.
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
What am I missing? Is the cross domain issue a red herring and there is something else going on that I am missing. Any suggestions on what to do?
EDIT: Not sure it matters but to be clear we are using HTTPS in both environments and when accessing the contingency server I use the fully qualified machine name as the DNS is set up to point to the primary server.
My Question: How can i query/list the contents of the cache.
So i have creates one cache from Management API->Environment Configuration.
Then i created a api proxy with no target and attached populate cache policy to it. e.g.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PopulateCache async="false" continueOnError="false" enabled="true" name="populateBlacklistByIP">
<DisplayName>populateBlacklistByIP</DisplayName>
<FaultRules/>
<Properties/>
<CacheKey>
<Prefix>CLIENTIP-</Prefix>
<KeyFragment ref='request.queryparam.myvar'/>
</CacheKey>
<CacheResource>mycache</CacheResource>
<Scope>Global</Scope>
<!-- no expiry -->
<ExpirySettings>
<TimeoutInSec>432000</TimeoutInSec>
</ExpirySettings>
<Source>request.queryparam.myvar</Source>
</PopulateCache>
Now i invoke the operation and get 200 ok back. But no way to check if the value made to cache or not.
Please help.
Got My Answer from digging through the documentation.
Ref: http://apigee.com/docs/api-services/content/persistence.
Read this from url above:
Cache versus Key/value map
The PopulateCache policy does not persist cache entries. Entries are in memory until the configured expiration time. You can look up the value only until it expires.
One limitation is that you cannot find the list of keys that are currently in a cache.
When using KeyValueMap, the keys are persisted indefinitely. There are APIs available to retrieve the list of keys. There is no expiration time for the keys; you must explicitly delete them.
The problem is: I need to connect to a soap web service; generated by java code; using ASP.Net client via C# through MS Visual Studio 2013.
Try 1, The usual way:
I have added a web service reference using the wsdl and by assigning the credentials like:
Credentials.Username.Username = "test";
Credentials.Password.Password = "test";
When executing, the following exception is being encountered:
The login information is missing!
Try 2:
I have searched for similar problems like:
how-to-go-from-wsdl-soap-request-envelope-in-c-sharp
Dynamic-Proxy-Creation-Using-C-Emit
c# - Client to send SOAP request and received response
I had chosen to generate a proxy class using the wsdl tool, then added the
header attribute, but I have found the following note from Microsoft:
Note: If the Web service defines the member variables representing the SOAP headers of type SoapHeader or SoapUnknownHeader instead of a class deriving from SoapHeader, a proxy class will not have any information about that SOAP header.
Try 3:
I have tried to change the service model in the client web.config:
<bindings>
<basicHttpBinding>
<binding name="CallingCardServicePortBinding">
<security mode="TransportWithMessageCredential" >
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Then added the credentials like the first try, but the following error appears:
MustUnderstand headers:[{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood
So, now I don't know what to do !
I have no control over the web service and I need to build a client that understands it.
Help Please!
The Soap Request template is the following:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="...">
<soapenv:Header>
<credentials>
<userName>someUserName</userName>
<password>somePassword</password>
</credentials>
</soapenv:Header>
<soapenv:Body>
<ser:someRequest>
.......
.......
.......
</ser:someRequest>
If the destination web service uses authentication, then just ASMX won't do, since it is not aware of authentication, encryption etc. You have 2 options:
Use Microsoft WSE: http://www.microsoft.com/en-us/download/details.aspx?id=14089
this is nothing but an extension of ASMX which makes it Security/Encryption aware. (and some other features) technically, you'll be adding a reference to the WSE DLL and your Soap Proxy will extend from the WSE SOAP Client instead of the System one.
once you do that, the proxy class will have additional username/password properties that you can use to authenticate properly.
set the properties and see the outgoing request using fiddler. if the header is not what you want (because of namespaces etc.), then you can write a custom outgoing message inspector and modify the soap request nicely.
The other option (preferred) is to use WCF.
ASMX and WSE are older than WCF. WCF tries to bring all the web service nuances under one roof. if you get a WCF service reference, it (svcutil.exe) will automatically create the proxy class and the right bindings for you. (mostly custom)
once you do that, try setting the user name and password.
if that doesn't work, (i have frequently struggled to generate the right soap header for remote java based services that require username/password authentication), you can define a static header chunk in the web.config/app.config, that'll be sent as part of every request.
e.g.
<client>
<endpoint>
<headers>
<credentials>
<userName>someUserName</userName>
<password>somePassword</password>
</credentials>
</headers>
</endpoint>
</client>
I have set up a custom variable in my developer app called sandbox.app_id so I can have different ids for different applications.
I am using the verify api key policy and this populate the verifyapikey.* variables.
I want an ExtractVariable policy similar to below:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-TLRG-App-ID">
<DisplayName>Extract TLRG App ID</DisplayName>
<FaultRules/>
<Properties/>
<Variable name="app_id">verifyapikey.verify-api-key.{environment.name}.app_id</Variable>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<VariablePrefix>apigee</VariablePrefix>
</ExtractVariables>
Is this possible, or will I have to resort to javascript?
Basically you are trying to access custom application attributes from your extract variable policy. So you need to place this extract variable policy after your verify api key policy. A verify api key policy would load all the application attributes as flow variables for a valid key. You may not see the custom attributes as variables in the debug view. However correct way to access the variables is to use this naming format below:
verifyapikey.{your_policy_name}.app.{custom_attribute_name}
Note that the verify api key policy is mandatory, otherwise the application associated with the API call can not be identified.