I am trying to set up WSO2 Identity Server behind a reverse proxy for SSL offloading. For example, let's say if WSO2 IS is available at say https://<some-ip>:9443/, I am trying to put it behind reverse proxy with address such as https://<domain name>/is/. Note the context path /is and SSL port 443. I thought that this will be trivial enough but sadly I am unable to find any conclusive documentation for achieving the same.
My applications are using OIDC to connect to WSO2 IS and using Azure Application Gateway as reverse proxy - typically all API calls works well but neither of UI (or flows involving redirections) works due to context. I can also fix redirects by URL rewriting at reverse proxy but that still doesn't solve problems. For example, login page will appear but XHR call from the same will go to /logincontext instead of /is/logincontext. Where can I set up the proxy context path in WSO2 IS? I already tried setting the same in .toml file (equivalent of setting it in carbon.xml) but it seems to be affecting only Management Portal.
WSo2 IS documentation talks about setting it up behind ngnix but that documentation is not using any path context. I could find reverse proxy documentation for other WSO2 product such as WSO2 API Manager but it only involves updating carbon.xml and that doesn't work for WSO2 IS. I am not a java person and hence, finding it difficult to figure out web app organization of WSO2.
Any help/link to documentation/guide to set up with proxy context will be useful.
I know that this answer comes a little bit late but recently I had a similar issue and here it is how I made it work, maybe it could be helpful for someone. I was using WSO2 IS 5.11.0.
Note:
I checked similar questions on stackoverflow and found a few but none was enough by itself for my case.
Maybe the solution I came up with is not the best or the most correct but it is the only one I could make work.
Here's how I did, assuming the context path is is:
Open Carbon Management Console and go to Identity Providers -> Resident. Then, go to Inbound Authentication Configuration -> OAuth2/OpenID Connect Configuration. Here, change the hostname under Identity Provider Entity ID to https://domain_name:443/is/<remaining path>.
Make sure that the port number is present or absent both here and in the client application. If there is a mismatch between the two, for some reason, it won't work (or at least it didn't for me).
Open the file deployment.toml and modify it as follows:
under the [server] section, add your proxy context at the end of the base_path url, e.g. base_path = "https://$ref{server.hostname}:${carbon.management.port}/is";
of course, also add proxy_context_path = "is" (actually, this last line should be enough but for some reason in my case it wasn't, so I had to modify the base path too);
under [transport.https.properties] add proxyPort="443".
For the record, I also turned off compression, by adding:
[transport.http.properties]
compression="off"
[transport.https.properties]
...
compression="off"
and set the token issuer URL equal to the entity id set up in Carbon, with:
[oauth]
use_entityid_as_issuer_in_oidc_discovery = true
but found out that these last two steps (turning off compression and setting the entity id as issuer) weren't needed.
Disable the csrf guard by setting org.owasp.csrfguard.Enabled = false
in the file /repository/resources/conf/templates/repository/conf/security/Owasp.CsrfGuard.Carbon.properties.j2.
This step was necessary for me to avoid the 403 Error after logging in on the Carbon Console (turning off compression didn't work).
Lastly, if you use nginx as reverse proxy (as I did), add these two lines in the location used for wso2:
proxy_redirect https://domain_name/oauth2/ https://domain_name/is/oauth2/;
proxy_redirect https://domain_name/carbon/ https://domain_name/is/carbon/;
These are needed (or at least were for me) because some URLs are not under the context path. In particular, the last one allows you to open the Carbon Console at https://domain_name/is/carbon/.
References:
wso2 api manger carbon page gives 403 Forbidden
WSO2 Identity Server login returns a 403
WSO2 Identity Server port configuration
To understand the template-based configuration model adopted from version 5.9.0 onwards, see:
https://apim.docs.wso2.com/en/latest/reference/understanding-the-new-configuration-model/
https://mcvidanagama.medium.com/understand-wso2-api-managers-new-configuration-model-6425a2710faa
Here are some useful configuration mappings from the old xml to the new toml based model:
https://github.com/ayshsandu/samples/tree/master/config-mapping
Related
The problem I am facing is that after changing the hostname and configuring the reverse proxy as described here and here, as well as following the troubleshooting guide here to resolve the 'the registered callback does not match' I am unable to get any further.
I've followed a number of other examples of how to configure nginx and add the reverseProxy property to the settings.js configs but with no luck.
As you can see below if I go to https://example.com/publisher I continue getting the error 'The registered callback does not match'
Here is what I have the callback regex set to:
regexp=(https://example.com/publisher/services/auth/callback/login|https://example.com/publisher/services/auth/callback/logout)
If I inspect the authorize request query I can see that the redirect_url is being set to 127.0.0.1 and I suspect that is the problem as when I add that url to the service provider regex callback it works, but this is not suitable in a non local environment.
And here is the request query (where I suspect the main issue lies - note redirect_uri):
https://example.com/oauth2/authorize?response_type=code&client_id=1obvNiUMBcJwMa3euoHjrsckuGIa&scope=apim:api_create%20apim:api_delete%20apim:api_import_export%20apim:api_product_import_export%20apim:api_publish%20apim:api_view%20apim:app_import_export%20apim:client_certificates_add%20apim:client_certificates_update%20apim:client_certificates_view%20apim:document_create%20apim:document_manage%20apim:ep_certificates_add%20apim:ep_certificates_update%20apim:ep_certificates_view%20apim:external_services_discover%20apim:mediation_policy_create%20apim:mediation_policy_manage%20apim:mediation_policy_view%20apim:pub_alert_manage%20apim:publisher_settings%20apim:shared_scope_manage%20apim:subscription_block%20apim:subscription_view%20apim:threat_protection_policy_create%20apim:threat_protection_policy_manage%20openid&state=/&redirect_uri=https://127.0.0.1/publisher/services/auth/callback/login
Here is how my deployment.toml is configured (I've replaced my actual domain with example.com):
Note I had to remove the ports to work behind the proxy
And here is my settings.js:
I added the reverseProxy property as suggested in a github issue
And here is my nginx conf:
This is a known limitation. Please find the steps to resolve the issue - https://apim.docs.wso2.com/en/latest/troubleshooting/troubleshooting-invalid-callback-error/#troubleshooting-registered-callback-does-not-match-with-the-provided-url-error
The reason for this error comes down to a missing X-Forwarded-For header, I ended up changing the forwardedHeader in settings.js to Host as that was being passed from my proxy server.
Thanks for the detailed question "user3745065".
I was having the exactly same issue you described in this post, and I guess I nailed the problem down.
Like you mentioned the issue is with the forwardedHeader, that in your case you switched to Host.
But checking the product documentation, the sample they provide is the following:
customUrl: { // Dynamically set the redirect origin according to the forwardedHeader host|proxyPort combination
enabled: true,
forwardedHeader: 'X-Forwarded-Host',
},
It took me a while to noticed that the forwardedHeader is supposed to be 'X-Forwarded-Host' not 'X-Forwarded-For' as it comes as default.
Few other things I needed to tweak that wasn't clear in the documentation for changing the hostname (here), I had to remove the port variable ${mgt.transport.https.port} from devportal.
That's outlined on the installation step 5 also, here. However worth mentioning:
from:
[apim.devportal]
url = "https://{Your Domain}:${mgt.transport.https.port}/devportal"
to
url = "https://{Your Domain}/devportal"
otherwise when the it tries to redirect to the portal (for instance, from the publisher) it construct the url with the port number, and that default port 9443 isn't going to work on your proxy (tested on nginx with the provided settings that is on the documentation here) which is listening and expecting calls on port 443.
Things that I noticed you configured but perhaps it's not necessary:
Set the apim.idp settings
Set the reverseProxy settings
Set the apim.gateway.environment settings (Not related to the callback url issue, this is meant for you to configure the runtime gateway urls)
Last but not the least, Following the "Troubleshooting 'Registered callback does not match with the provided url' error", again you need to remove the port number from the url, otherwise you will have the same issue aforementioned on your proxy.
Just my 2 cents! ;)
I need to add a WebRootContext to all the calls in the WSO2 Identity Server's Implicit Flow so that I can make calls through an API Gateway. I have managed to do this for all the calls I need by changing the
<WebContextRoot>/wso2-is<WebContextRoot>
property as well as changing the name of my webapp folders: wso2-is#authenticationendpoint and wso2-is#oauth2 endpoints. I can now successfully call http://localhost:9443/wso2-is/oauth2/authorize.
I also changed the endpoints in repository/conf/identity/identity.xml to include the wso2-is root context, specifically the OAuth2AuthzEPUrl, so that in the management console this shows up under identity:
However, after I login, the application calls http://localhost:9443/wso2-is/commonauth which has a return location of http://localhost:9443/oauth2/authorize?sessionDataKey=... and I can't figure out how to add my context root to the returning call. Where does the commonauth endpoint get the location it returns to? I'm assuming there is some property I need to set to make that happen, but I can't find it.
I also tried re-seeding the database with all my changes and this did not solve my issue either.
I looked in the source code here in github and couldn't find any references to commonauth or oauth2/authorize that stood out as to where this call is being formed. Any additional details would be greatly appreciated.
As per the official documentation, using a reverse proxy is the recommended way to add a custom context path to wso2 products.
However, as I wrote in another question, I could complete the implicit flow with local auth successfully with the mentioned configs in my answer.
I guess, what you are missing here is ProxyContextPath.
I'm running WSO2 5.7.0, using OIDC with the Implicit Flow. I have set the context root to wso2-is, so the authorize endpoint is located at http://MY_DOMAIN/wso2-is/oauth2/authorize. When I begin the flow with a GET call to the oauth2/authorizeendpoint, I am redirected to http://MY_DOMAIN/authenticationendpoint/login.do?client_id=MY_CLIENT_ID&commonAuthCallerPath=%2Foauth2%2Fauthorize....
The problem is that it drops the context root and so later in the Implicit Flow I am (incorrectly) redirected to http://MY_DOMAIN/oauth2/authorize, which fails because that URL lacks the context root of wso2-is. How/where in the code is the commonAuthCallerPath parameter set?
As per the official documentation, using a reverse proxy is the recommended way to add a custom context path to wso2 products.
If you are not going to use a reverse proxy, I would suggest the following steps to add a custom context path. But, note that I have tested basic authentication with oauth2/oidc only.
Set WebContextRoot in repository/conf/carbon.xml to /wso2-is to change the context path of the carbon management console
Set ProxyContextPath in repository/conf/carbon.xml to /wso2-is
Rename oauth2.war and authenticationendpoint.war in repository/deployment/server/webapps/ by adding a prefix wso2-is#
Update repository/conf/indeitiy/identity.xml all the relevent instances of the following pattern by adding the context path /wso2-is after the port
${carbon.protocol}://${carbon.host}:${carbon.management.port}/xxxxx
to
${carbon.protocol}://${carbon.host}:${carbon.management.port}/wso2-is/xxxxx
Update AuthenticationEndpointURL, AuthenticationEndpointRetryURL and AuthenticationEndpointMissingClaimsURL values in repository/conf/identity/application-authentication.xml by adding /wso2-is prefix
Restart the Identity Server
Do not forget that, this is not the recommended way in the documentation.
I have tried everything but I cant seem to fix this issue that is happening for only one client behind a corporate proxy/firewall. Our Silverlight application connects to Amazon S3 for downloading/Uploading some documents. On one client and one client only it returns a 407 error and after that the application fails to save anything.
Inner Exception:
System.ServiceModel.ProtocolException: [UnexpectedHttpResponseCode]
Arguments: 407,Proxy Authentication Required
We had something similar at a different client but there was more of a CORS issue. to resolve this I used cloud-front to fake a sub-domain that then accesses the S3 bucket and it solved the issue. I was hoping it would fix it with this client as well but it didnt.
I have tried adding this code to web.config as suggested by a lot of answers
<system.net>
<defaultProxy useDefaultCredentials="true" >
</defaultProxy>
</system.net>
I have read articles about passing a proxy headers with basis authentication using username and password but I am not sure how this would help us. The Proxy server is used by client and any authentication it requires is outside our domain.
**Additional Information**
The Silverlight code references 2 services. One is our wcf service that retrieves all the data for the application. One is The Amazon S3 service that uses the amazon Soap api, the endpoint for which is at http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl?
If I go into our app and only use part of the system that dont make any calls to the Amazon S3 api the application works fine. As soon as I go to a part of the system that makes a call to the S3, the problem starts. funny enough the call to S3 goes fine and I can retrieve the doc fine but then any calls to our wcf service return 407.
Any ideas?
**Update 2**
Based on comments from Elliot Nelson I check the stack we were using for making http requests in our application. Turns out we are using client http for both http and https requests by default. Here is the code we have in the App.xaml constructor
public App()
{
Startup += Application_Startup;
UnhandledException += Application_UnhandledException;
InitializeComponent();
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
}
Now, to understand the differences between clienthttp and browserhttp and when to use them. Also, the potential impacts/issues of switching to browserhttp.
**Update 3**
Is there a way to request browsers to run your in-browser Silverlight application in trusted mode and would it help bypass this issue?
(Answer #2)
So, most likely (for corporate environments like this network), almost nothing can be done without whatever custom proxy settings are set in IE, usually pushed by corporate policy. To take advantage of these proxy settings, you want to use WebRequestCreator.BrowserHttp, which automatically uses the browser's default settings when making requests.
There's a table of the differences between these two clients available in the Microsoft docs. I'm guessing you were using something (maybe setting custom headers or reading the raw response body) that wasn't supported in BrowserHttp.
For security reasons, you can't "ask" the browser what its proxy settings are and use them, so this is a tricky situation. You can specify Browser vs Client handling by domain, or even for a specific request (the same page above describes how); you may be able in this case to get away with just using ClientHttp for your service calls and BrowserHttp for your S3 calls, and avoid the problem altogether!
For next steps, I'd try that approach; if it doesn't work, I'd try switching wholesale to BrowserHttp just to see if it bypasses the proxy issue (there's almost no chance the application will actually work, since you're probably using ClientHttp-only options).
Long term, you may want to consider making changes to your services so they are usable by a BrowserHttp-only application (this would require you to be pretty basic in your requests/responses, but using only BrowserHttp would be a guarantee you'd work in pretty much any corp network).
Running in trusted mode is probably a group policy thing which would require their AD admins to approve / whitelist your app.
I think the underlying issue you are facing is that the proxy requires NTLM authentication and for whatever reason the browser declines to provide your app with that context.
One way to prove that it's an NTLM auth issue is to test with curl - get it to make a req through the proxy, then it should be a bit easier to code to. EG the following curl will get you through 99% of Windows corporate proxies (assuming the proxy is at proxy-host.corp:3128):
C:\> curl.exe -v --proxy proxy-host:3128 --proxy-user : --proxy-ntlm https://www.google.com
NOTE The --proxy-user : tells curl to use the current user session to perform the NTLM challenge.
So if you can get the client to run that, you can at least identify that NTLM works, then it's a just a matter of getting the app to perform the NTLM challenge using the default credentials (which may or may not be provided by the browser session)
Since you described this as a silverlight application, I'm going to assume you can't use classic browser-proxy troubleshooting like "move browser to public network" or "try a different browser", to isolate the problem.
You should try to isolate the proxy server, and have the customer use the required proxy-auth.
The application is making request, but it might be intercepted by a transparent proxy, or the result might be coming from what you consider a web server.
In the early days, the 401 error was pretty strictly associated with web-auth, and 407 was for proxy-auth.
Architecturally, the separation is a convenience, a web server can have both web server, proxy, and reverse-proxy behaviors.
What happens is your customer's environment is making a web connection to the destination, but it receives a HTTP 407 status from some host, probably their network, or sometimes the provider. Almost certainly the request is received not forwarded. The HTTP client your application lives in needs to provide the credentials that host requires. Companies have environments that are complex enough where often your customer will say this is the first time they have heard of this (some proxy-auth is also dynamic or destination specific).
Also, in some corporate environments, the operator will allow temporary or permanent white-listing from the proxy-auth service. You should see if they can do this, even temporarily, to confirm there aren't going to be other problems.
In the end, it sounds like your application might not robustly support proxy-auth, or the proxy-auth type they use in their environment.
I`m working on a SAP project, where i have to call a non-sap service with jsessionid in binding url. I already generated a proxy class out of the wsdl and defined a logical port with my URL. In my case it should be dynamic like: {host}/service/foo/binding;jsessionid={xxx} but its static like: {host}/service/foo/binding
How can i achieve that session handling?
EDIT: The problem here is, its not only for authentification its also for load balancing. The jsessionid MUST be submitted via URL rewriting. Any ideas?
You should be able to configure this with the soamanager transaction:
Go to the service configuration screen and select your consumer proxy
Edit the existing, or create a new logical port
Go to the transport settings tab and change the URL access path
Once saved, you can find the logical port as a destination in transaction SM59. It's one of the generated ones in the external HTTP connections tree.
Providing a value for the parameter will probably require a modification of the SAP software though. The system uses the cl_http_client=>create_by_destination method to obtain a client object to perform the http call, so maybe you can implement some custom code there.