Target Endpoint requires Basic Auth with authorization header but keep getting a 500 Internal server error

I seem to be going round in circles with trying to implement an API proxy in which the target endpoint uses basic auth [username] and [password] and expects an authorization header.

Using the basic auth policy on the target preflow i have it as follows :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BasicAuthentication async="false" continueOnError="false" enabled="true" name="Basic-Authentication-2">
    <DisplayName>Basic Authentication-1</DisplayName>
    <Operation>Decode</Operation>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <User ref="request.header.username"/>
    <Password ref="request.header.password"/>
    <AssignTo createNew="false">request.header.Authorization</AssignTo>
    <Source>request.header.Authorization</Source>
</BasicAuthentication>
Solved Solved
0 15 4,207
1 ACCEPTED SOLUTION

You are using decode operation , does the request already have Basic base64encodedstring in Authorization header required by target system ?

Basic Authentication supports outbound encoding and inbound decoding.

Outbound Encoding

When request have username and password in simple text and it need to be encoded and added to authorization header(or anywhere else) before hitting target.

Below code will take simple text username and password from request headers , base64 encode it and set it to Authorization header.

<BasicAuthentication name="ApplyBasicAuthHeader">
   <DisplayName>ApplyBasicAuthHeader</DisplayName>
   <Operation>Encode</Operation>
   <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
   <User ref="request.header.username" />
   <Password ref="request.header.password" />
   <AssignTo createNew="false">request.header.Authorization</AssignTo>
</BasicAuthentication>

Inbound Decoding

When request/response contains base64encoded string and need to decode it in simple text for furthur use.

Below code will take value of authorization header (Basic <base64encodedstring> ) , decode it and assign it to username and password headers.

<BasicAuthentication name="DecodeBaseAuthHeaders">
   <DisplayName>Decode Basic Authentication Header</DisplayName>
   <Operation>Decode</Operation>
   <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
   <User ref="request.header.username" />
   <Password ref="request.header.password" />
   <Source>request.header.Authorization</Source>
</BasicAuthentication>

Please take this docs refrence for furthur clarification and configure policy according to your need.

Hope this will help !!!

View solution in original post

15 REPLIES 15

Hi @Sanchez, In Basic Authentication policy, we have two operations. Decode & Encode.

You need to use Encode to get an Base64 string based on username & password.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BasicAuthentication async="false" continueOnError="false" enabled="true" name="Basic-Authentication-2">
    <DisplayName>Basic Authentication-1</DisplayName>
    <Operation>Encode</Operation>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <User ref="request.header.username"/>
    <Password ref="request.header.password"/>
    <AssignTo createNew="false">request.header.Authorization</AssignTo>
</BasicAuthentication>

Thanks @Siddharth Barahalikar yes i'm trying to use Encode but uploaded incorrect snippet as was looking at the Decode alternative also at the time.

So what i have done now is i have the BA policy as follows :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BasicAuthentication async="false" continueOnError="false" enabled="true" name="BA-Set-Authorization">
    <DisplayName>BA-Set-Authorization</DisplayName>
    <Operation>Encode</Operation>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <User ref="private.username"/>
    <Password ref="private.password"/>
    <AssignTo createNew="false">request.header.Authorization</AssignTo>
</BasicAuthentication>

As i created a KVM (encrypted) policy to go with it before the BA policy in the proxy preflow as follows :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<KeyValueMapOperations async="false" continueOnError="false" enabled="true" name="KVM-Get-User-Credentials" mapIdentifier="mdaUserCreds">
    <DisplayName>KVM-Get-User-Credentials</DisplayName>
    <Properties/>
    <ExclusiveCache>false</ExclusiveCache>
    <ExpiryTimeInSecs>300</ExpiryTimeInSecs>
    <Get assignTo="private.username" index="1">
        <Key>
            <Parameter>username</Parameter>
        </Key>
    </Get>
    <Get assignTo="private.password" index="1">
        <Key>
            <Parameter>password</Parameter>
        </Key>
    </Get>
    <Scope>environment</Scope>
</KeyValueMapOperations>

When i trace using the apigee proxy via trace the response from the target server is :

Response received from target server
                                
                                    500
                                
                                    Internal Server Error                        

This is also the same if i use postman with the Apigee proxy url.

If i make the request in postman using the target url in postman i get a valid response.

Any ideas?

And just to add to my previous comment if i use the browser using the required BA for the proxy created i get the following error (500 internal) :

7258-09-08-2018-15-53-07.png

yet if i use the target endpoint in the browser i get a valid response :

7260-09-08-2018-16-00-51.png

One of the ways you could troubleshoot is to see how Apigee is calling your target endpoint -https://docs.apigee.com/api-platform/debug/using-trace-tool-0#showingrequestsascurl

Copy the curl and see if your target works with these params, i suspect the requests are different

@gnanasekaran thanks as yes ive used that and noticed that the auth header is the only thing being sent to the target when the target needs username , password and header . So looks like the KVM isnt the way to do this then maybe and just trying to find appropriate documentation for this as just keep going round in circles here. There should really be some decent examples for users to follow as keep seeing different methods being used which is confusing.

Would you know how this is achieved then by any chance?

what you are doing seem to be correct, are you noticing Apigee not sending the basic auth credentials?

Thats correct its only sending the Authorization header value but not the username and password also to the target which it requires

Sorry, I am missing the context, the policies you have should result in a curl from apigee like this,

`curl -H 'Authorization: Basic dXNlcjpwYXNz' https://your-target-url/`

is this how you call the target? or do you also send user/pass separately? can you share sample calling your target directly?

The target needs username, password and Authorization header and the trace seems to show only Authorization being sent :

7276-13-08-2018-15-50-25.png

Ok, the policies you have configured will base64 encode the user/pass and add it to the Authorization header. The fact that you are receiving HTTP 500 instead of HTTP 401 confirms that. So far, this is working as expected.

Now, how do you want to pass the user/pass - depending on how you want to pass it, we could use policies to do that [for eg, a header]

[fwiw - you already have basic auth, passing user/pass seem redundant]

can you share a sample call to target, maybe your postman client screenshot would help, thanks

yes the target requires all three being username, password and auth header .

when using Postman that is what i have to use on the target to get a response

Thanks, now its clear, - Postman collects the user/pass and generates a auth header, it won't send user/pass separately.

Looks like some other problem, calling from apigee - needs some more troubleshooting,

- can you confirm if the Auth header in trace is equal to the one on Postman [should be equal]

- possibly one of the headers is causing the issue - can you try the curl copied from trace, see if you get the same error, and try removing one header at a time and see if it resolves - if it does, then we could remove those headers in Apigee, but this needs to be verified

- yes the auth header in the trace is exactly the same as the one in postman.

- The curl in the trace is the target server being used in postman also and works perfectly fine.


You are using decode operation , does the request already have Basic base64encodedstring in Authorization header required by target system ?

Basic Authentication supports outbound encoding and inbound decoding.

Outbound Encoding

When request have username and password in simple text and it need to be encoded and added to authorization header(or anywhere else) before hitting target.

Below code will take simple text username and password from request headers , base64 encode it and set it to Authorization header.

<BasicAuthentication name="ApplyBasicAuthHeader">
   <DisplayName>ApplyBasicAuthHeader</DisplayName>
   <Operation>Encode</Operation>
   <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
   <User ref="request.header.username" />
   <Password ref="request.header.password" />
   <AssignTo createNew="false">request.header.Authorization</AssignTo>
</BasicAuthentication>

Inbound Decoding

When request/response contains base64encoded string and need to decode it in simple text for furthur use.

Below code will take value of authorization header (Basic <base64encodedstring> ) , decode it and assign it to username and password headers.

<BasicAuthentication name="DecodeBaseAuthHeaders">
   <DisplayName>Decode Basic Authentication Header</DisplayName>
   <Operation>Decode</Operation>
   <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
   <User ref="request.header.username" />
   <Password ref="request.header.password" />
   <Source>request.header.Authorization</Source>
</BasicAuthentication>

Please take this docs refrence for furthur clarification and configure policy according to your need.

Hope this will help !!!

For anyone in a similar situation, what resolved this for me was introducing an assign message policy in respect to the header.

Some of which is detailed here :

https://docs.apigee.com/api-platform/tutorials/secure-calls-your-api-through-api-key-validation#extr...