Shibboleth SP: How to pass NameID in an http header? - saml-2.0

My web app is secured by reverse proxy where shibboleth sp does its magic. I recieve a saml response where i have custom name id. How do I pass it in a custom header to my web app?

Using ajp
ProxyPass /secure ajp://localhost:8009/MyApp/secure
ProxyPassReverse /secure ajp://localhost:8009/MyApp/secure
here 8009 is port of ajp so put this only, even if your app would work on 8080.
Another thing, in your shibboleth2.xml, in the ApplicationDefaults tag add attribute attributePrefix="AJP_", so every attribute would be prefixed with ajp and you can get it with, request.getHeader("AJP_NameID");.

Related

Kubernetes and AAD authentication

On configured AKS there is docker container with application that is using AAD authentication.
Based on this article there is also configured ingress. API is working well.
When I add to Azure Active Directory application registration reply URL with https prefix I receive error "The reply url specified in the request does not match the reply urls configured for the application". And I see that in browser address line redirect_uri is starting with http.
When I add reply URL that is starting with http, then I receive "Exception: Correlation failed".
What I have tried: Add to ingress.yaml setting ingress.kubernetes.io/force-ssl-redirect: "true"
May be there is some way to force ingress run https instead of http, or there might be some AAD redirect configuration? Any ideas?
UPDATE 2: Probably http redirect is because of ADAL.
PS: Was able to find similar topic without an answer
UPDATE3:
I have decided not to use nginx as ingress. Instead I am using now Load balancer. Soon it would be possible to use Azure Application Gateway Ingress Controller
Have you tried this?
By default the controller redirects HTTP clients to the HTTPS port 443 using a 308 Permanent Redirect response if TLS is enabled for that Ingress.
This can be disabled globally using ssl-redirect: "false" in the NGINX config map, or per-Ingress with the nginx.ingress.kubernetes.io/ssl-redirect: "false" annotation in the particular resource.
More information on this on the Ingress documentation link.
You have to make a decision whether to use HTTPS or not. If this is just the start of a development cycle, start without it and get auth to work - but implement HTTPS as soon as possible.
AAD supports both http and https, but of course, the reply urls must be added to the application registration respectively.
As #mihail-stancescu says, ssl-redirect must be set to false, if you choose not to use HTTPS. In addition to this, you also have to ensure that your app does not make the redirect from HTTP to HTTPS.
Using curl with -L -k and -v options will give you a lot of information on what is actually happening with your requests.
When the http/https thing is solved, you have to remove any rewrite annotations you have in your ingress. (e.g. ingress.kubernetes.io/rewrite-target: / should be removed).
Now, if your ingress path to the service in question is e.g. /myservice, then the reply-url should also have that part of the path added ([host]/myservice/signin-oidc) - both in the AAD application registration and in the configuration of your app. (The path in the config should not contain the host)
If you are using https, then you must also have a proper certificate. You can use the free LetsEncrypt (https://letsencrypt.org/) in conjunction with KubeLego (https://github.com/jetstack/kube-lego), where you can find some nice examples on how to implement it.

Catch 302 with Apache and return 401 instead

We currently have a shibboleth implementation that protects a certain path. However, because this path is actually an HTTP request (made with an AngularJS app using $http), shibboleth will try to "redirect" this request to the Identity Provider, but the browser simply interprets this as a dead request. It gets returned to AngularJS with status=-1 and no associated headers/data.
I would like to intercept this 302 and instead return a 401, and preferably be able to edit the response headers. Are there any ways to do this using Apache or Shibboleth?
Relevant blocks:
# Proxy all requests to WebLogic
<Location "/api">
SetHandler weblogic-handler
WLSRequest On
WebLogicHost services.endpoint.com
WebLogicPort 9002
</Location>
# For requests marked as protected, apply shibboleth
# If this block gets triggered, Shibboleth attempts redirect
# which does not work with our architecture
<Location "/api/protected">
AuthType Shibboleth
ShibRequireSession On
ShibApplicationId default
ShibExportAssertion On
Require Shibboleth
</Location>
How it's used in AngularJS:
//API call to unprotected endpoint
$http.get('http://hosted.on.apache.com/api/getData');
//API call to protected endpoint - Shibboleth triggered
$http.get('http://hosted.on.apache.com/api/protected/getSecureData');
I'm not familiar with Sibboleth, but as people have pointed out in the comments this can easily be accomplished with a reverse proxy.
See the solutions suggested in this answer as a reference:
Apache - Reverse Proxy and HTTP 302 status message
It seems like this is not possible to do, as the 302 redirect sent by Shibboleth is simply forwarded to the caller by Apache (as it is not an error).
Instead of battling the redirects, have single endpoint being protected by Shibboleth. If successful, this endpoint sets two cookies:
A secure, http-only session cookie that is used as a login token by every other endpoint.
A secure timeout cookie that tells the frontend when the session runs out, to be able to communicate to the user that their session is about to end, and to stop any ajax-calls when the session has ended.
If there is still a valid shibboleth session when /login is called again, the session cookies will be reissued.
In Apache
<Location /login>
# Let Shibboleth handle the creation of a valid session
AuthType shibboleth
ShibRequireSession On
ShibUseHeaders On
require valid-user
# set session cookie
# set timeout cookie
Well I think redirecting a 302 to a 404 is not necessary.
Try adding to your /api/protected area the following.
ShibRequestSetting requireSession 1
As per the documentation here this is what a typical protected path looks like.
https://docs.shib.ncsu.edu/docs/testing/index.html
<Location /api/protected>
AuthType shibboleth
ShibCompatWith24 On
ShibRequestSetting requireSession 1
require shib-session
</Location>

angular OPTIONS http preflight on "Same Domain"?

I am currently confused about how angular's (jquery) preflight OPTIONS call is "selected" or chosen to perform before a request.
I have a normal RESTful api call (api.domain.co)
I have created a host entry 127.0.0.1 local.domain.co in my hosts file /etc/hosts.
I've created self-signed certificate:
http://www.akadia.com/services/ssh_test_certificate.html
I've configured the certs in my mac as trusted:
http://abetobing.com/blog/port-forwarding-mac-os-yosemite-81.html
I've configured my Yosemite Port Forwarding Rules:
http://abetobing.com/blog/port-forwarding-mac-os-yosemite-81.html
I understand that from the browser's perspective (Chrome):
I have an angular app being loaded from https://local.domain.co with a trusted certificate that has a call to https://api.domain.co/user everything looks green with the cert, and I still get a preflight OPTIONS call to my api.domain.co server which is a node resitfy server with CORS support
Everything is Working... BUT
I want to get rid of the OPTIONS preflight Any pointers?
unfortunately subdomain still affected by preflight rule so if you want to remove OPTIONS you can either using jsonp or have the same subdomain for both the site & api.
You can't use localhost. I had to create an entry in my host file to associate 127.0.0.1 to an arbitrary name like mackbook. Then it should work for you.

Opensso with SSL Configuration issue in F5 Load Balancers

We are having a web application architecture where our application EAR is deployed in appServer configured with non-ssl Http Port Listener. Every request is routing via F5 Load Balancer-> Web Server-> App Server.
In Load Balancer, we have set an iRule where every Http Request is forwarded to Https set on port 443 and our application is working fine. Now we are trying to implement a SSO using OpenSSO federation solution and SAML Technology. we have deployed the opensso with the non-ssl http listener configuration in our app server.
now when we try to access the opensso using the url xhttp://domain_name/opensso(dummy protocol), it is redirected as per iRule set on the Load Balancer as xhttps://domain_name/opensso. But in the appearing configuration page of opensso, the server URL is populated as xhttp://domain_name only instead of xhttps://domain_name. Likewise, the same approach is followed to populate all the URL properties throughout the opensso configuration. So when I tried to generate the metadata using ssoadm GUI, In the form action attribute the url is formed as 'http' and the request method is passed as 'POST' only as per Opensso convention. But when it is redirected to 'https' as per the Load Balancer Rule the Request method is passed as 'GET' instead of post and the opensso validation fails and throwing the error as 'HTTP Post Protocol is required.
So the issue here is, By default the opensso URL properties should be populated with "https" instead of "http". I would like to know what is the wrong configuration done here. how we could resolve this issue? Thanks.
I think that you will find that the answer actually lies within your application server, not the application itself. You need to indicate to the servlet that it is being proxied, and that it is responsible for creating URLs with the HTTPS scheme, not HTTP.
If you're using Tomcat or a derivative, you can modify the server.xml to include the following:
proxyPort="443"
proxyName="www.domain_name.com"
scheme="https"
secure="true"
You can configure the load balancer to redirect to https with a 307 http status code which informs the client to use the original request method. If POST was the original request method then following the redirect the client will continue to use POST instead of a GET.
HTTP::respond 307 Location "https://[HTTP::host][HTTP::uri]"

wso2carbon Identity Server SSO redirect to port 9443

I'm using wso2 IS 4.8.0, my problem is that when I use the SAML2 SSO, I'm beeing redirect to port 9443 on the browser.
I want to be redirected to another port: 80 or 443, because there is an apache that proxies everything.
Is there a configuration to point the rediret to these ports?
Try adding proxyPort to catalina-server.xml which can be found at <IS_HOME>/repository/conf/tomcat folder as follows,
<Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
port="9443"
proxyPort="443"
And you'll need to change redirect url of ssoservice as well which can be found in <IS_HOME>/repository/conf/identity.xml file. Find for <SSOService> tag and edit <IdentityProviderURL> like follows,
<IdentityProviderURL>https://localhost:443/samlsso</IdentityProviderURL>
EDIT : Better to use IdentityProviderURL without the default port.
<IdentityProviderURL>https://localhost/samlsso</IdentityProviderURL>
Since 443 is the default port and there might be validation fails when it redirect to url with port and original request sent without the port.
HTH,
DarRay.

Resources