Overview
There are two domains: domainA and domainB. I am seeking to make the configuration, so that a web server from domainB can leverage an AD service account in another domainA.
In the environment where domainB is located, I have a web server that needs to reach back to domainA to be able to query all of the users. The owners of the domainA account created a service account user that allows domainB to query the user base. We have established that the account works when testing directly from the domainB controller to the domainA controller. When we try to run a ldapsearch from the web server using the service account user, we run into some issues:
[ec2-user#hostname ~]$ ldapsearch -x -LLL -h $domainB_ipAddress -D $service_account_username -w $ad_pwd -b "OU=xxxxx,DC=xxxxx,DC=xxxxx,DC=xxxxx"
ldap_bind: Invalid credentials (49)
additional info: 80090308: LdapErr: DSID-0C09042A, comment: AcceptSecurityContext error, data 52e, v3839
Note: This user is successfully authenticated from the domainB AD controller to the domainA AD controller using ldp.exe bind, so I believe the credentials are ok.
Our Current Approach
Based on the feedback I have received from my team, we should be making the request of the service account from domainB web server to the domainB controller, which will then forward this information on to the trusted domainA controller and return back the desired information back to the domainB web server.
I'm a little confused about how this forwarding is supposed to occur, but we have a requirement that we cannot reach directly into the domainA controller from any non-AD server from domainB.
Requested Feedback
Is it correct to assume that any request should be forwarded from the domainB controller to the domainA controller? If so, what needs to be in place for that to happen?
If requests cannot be forwarded, what would we need to do to get users from the trusted domainA into the domainB controller, so that the service account could reference them there?
This:
data 52e
Means:
ERROR_LOGON_FAILURE
1326 (0x52E)
The user name or password is incorrect.
You said the service account is from domainA, but you're connecting to domainB. That would only work if there is at least a one-way trust between the two domains: if domainB trusts domainA. From your description, I don't think that is the case. If you connect to domainB, you need to authenticate with a domainB account.
And the only way there would be any forwarding is if there was a trust. The term for this is a "referral". That would happen if there is a trust between the domains and you, for example, try to bind to a user in one domain while connected to the other. The server would return a "referral" telling you to go connect to the other domain.
Related
I have a scenario where I'm building an app that is hosted on an ubuntu server. Currently I have all inbound traffic to the server blocked with only outbound being allowed. The only way to access the React/Django app on the server is either thru VPN or having an IP whitelisted. When doing the OAuth1 process (to connect with a data provider), I'm struggling to figure out how to keep my app closed from the public internet but still complete the OAuth 1 process for the end user. Given that this app's purpose is to aggregate user data (from user's who've granted permission), it's not practical for me to whitelist the IP address of every single end user.
Currently, I'm considering making a form outside of my app for users to register with and then just having my app hourly check that form for new users so that it can then start the OAuth1 process and send the end user the authorization URL needed to grant permission to the data provider. At this point though, I have it where once the user signs up with their data provider, the callback URL redirects the user back to the Django app so that the Django app can grab the necessary elements from the URL in order to formally request for the user's actual access token. Given that the app is blocked to the public, I imagine the user won't actually be redirected back to the Django app for the access token part of the process to happen.
Any recommendations for this? For production?
I'm trying to setup a VPN connection using a federated login with Google IdP following these instructions.
Previously, I had configured a saml-provider with Google and it worked fine to authenticate users to the AWS console through Google using ARN roles
WHen I setup the VPN connection, it successfully opens the browser and asks me to select my google account, but after selecting the account I'm getting an error message from Google
According to this help section
Verify that the value in the saml:Issuer tag in the SAMLRequest matches the Entity ID value configured in the SAML Service Provider Details section in the Admin console. This value is case-sensitive.
So this is a problem coming from AWS and not from me ? Is Google IdP compatible at all with VPN authentication ? (I found this doc that mentions compatibility with okta)
Edit
Thanks to some of the answers below, I managed to make it work with Google IdP. Here is a screenshot of relevant SAML Google app screens (note that for groups I ended up adding the employees department, but I guess anything else would have worked)
To be able to save an ACS URL starting with http:// in the G Suite interface, use the trick given by teknowlogist: open the inspector > network tab, perform the request to save an URL with https, then right-click copy it as cURL, replace https by http, paste in regular console, and you're good.
I found a workaround to not being able to input http://127.0.0.1:35001 as the ACS URL on the GSuite SAML app page. The Google admin console only does client-side validation for the https requirement, so you can use the Chrome console to monitor the network call made when modifying the ACS URL.
Then, you can copy this as a curl command and change https to http
#Ted Schroeder —
Previous approach (or, plain Google doesn't work)
I just used a reverse proxy:
mitmproxy \
--listen-port 35000 \
--mode 'reverse:http://127.0.0.1:35001' \
--set keep_host_header=true
If you change Google SAML's ACS URL to be https://127.0.0.1:35000 and click "Test SAML Login", Google will take you to https://127.0.0.1:35000, whose traffic will be redirected to http://127.0.0.1:35001. In the browser I get:
Authentication details received, processing details. You may close this window at any time.
However, using the SAML-tracer extension, I found that there was a URL mismatch (https://127.0.0.1:35000 vs. http://127.0.0.1:35001). Seems like the AWS VPN Client is broadcasting its expected URL as being http://127.0.0.1:35001. So this doesn't seem viable.
Current approach (or, Auth0+Google works)
I tried using Auth0 instead, and got it to work! There's a few hoops — for instance, create a new Auth0 application, go to Addons and enable SAML2 Web App, set Application Callback URL to http://127.0.0.1:35001, and then in Settings use the following:
{
"audience": "urn:amazon:webservices:clientvpn",
"mappings": {
"user_id": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"email": "NameID",
"name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"given_name": "FirstName",
"family_name": "LastName",
"upn": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn",
"groups": "memberOf"
},
"binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",
"signResponse": true
}
Then users, if they download the VPN config from AWS and use the AWS VPN Client app, will be taken to an Auth0 login screen where they can login via Google. Voila! (And then for security, you need to add Auth0 Rules to grant only certain users/groups authorization.)
I don't have a full answer yet, but I have the beginnings of one and I actually got past the 403 error above. The key to all this can be found in the AWS Client VPN information here: https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html
Look for the section entitled "Service provider information for creating an app".
The key is that these are the ACS URL and the Entity ID that need to be used. Unfortunately, G Suite won't let you set the ACS URL to a non-https URL and apparently the AWS Client VPN app won't provide a secure URL for the ACS URL (where the SAML Authenticate response goes).
So, if you set the Entity ID to "urn:amazon:webservices:clientvpn" and have the G Suite SAML app in place according to the instructions, you'll get past the 403. However, since the ACS URL can't be specified you get whatever error message you're likely to get from the ACS URL that the authentication response goes to.
Example scenario
If you set it to https://signon.aws.amazon.com/saml" like you would for AWS Console SSO, you get an error from the AWS sign in that the SAML response was invalid.
And if you set it to https://127.0.0.1:35001 then you get a message from the browser that the "site can't provide a secure connection".
If anybody gets any further with this, I'd love to hear about it. In the meanwhile, I'm going to be looking into non-AWS OpenVPN clients that might actually support G Suite as a SAML IdP.
#alexandergunnarson
Since I don't have the ability to comment (thanks so much for making this easy stackOverflow) I had to edit my answer to get it past the censors.
Unfortunately, we don't have, and probably won't have for some time, G Suite Enterprise because it's too expensive for our startup environment. So OIDP is not a viable option for us now. I figured this would work. Good to know that it does.
I was too having the same issue. In my case, I needed to turn on the two-factor authentication for the account that I was trying to log in with.
I'm developing a web application which includes two separate servers:
A trusted server for private key operations
A webserver providing the frontend
Some operations on the webserver require private key operations. The webserver then asks the trusted server to perform the operation. In order to prevent misuse, the client needs to authorize each such request by providing a one-time password based on a pre-shared secret. The request should be authenticated by the webserver.
I was thinking about using a Popup in which the OTP should be entered. However, I'm not sure how to add authentication by the webserver in this scenario. Can you provide me with an idea how to achieve that?
So, we just got word today that one of our clients firewall is blocking our HTTP requests because "The [software] is sending anonymous packets to our firewall (a Microsoft TMG firewall) so the firewall is dropping the packets as anonymous access is [not] allowed."
For our connection code we are using c++ with curl and we fallback to IEDownloadToFile if needed. I didn't write the original code nor am I really a network programmer so I came here for help. So, my questions are: What are anonymous packets? What am I doing in curl that could cause anonymous packets? Where can I find more information about solving this problem? Thanks!
What they mean is your app has to authenticate with the firewall. That link provides a wealth of information concerning the TMG product. Your client probably has this configuration:
Require users to authenticate whenever
they request Web access. Every Web
session requires authentication.
When using this method, note the
following:
Anonymous Web access is disabled.
Forefront TMG requests user
credentials and validates them before
it checks the request against the
Firewall policy. If users fail to
authenticate, their access request is
denied.
This method is defined per network.
Most non-interactive clients, such as,
the Windows Update client, cannot
authenticate, and are therefore denied
access.
So when the user opens their web browser and tries to access a web page, they'll get a pop-up window asking for credentials because the firewall has intercepted their web request and sent its own authentication page. When the user authenticates, the firewall passes web traffic.
Your automated app does not authenticate with the firewall, so the firewall drops packets and your traffic is classified as anonymous.
Sorry, I don't know the solution on how to make your application authenticate with the firewall. If your app goes to specific URLs, the site operators could whitelist them.
According to this page, you should be getting error 407: proxy authentication required from curl. Try adding these options to the curl initialization, but you still have the problem of asking the user for their network credentials interactively:
CURLOPT_HTTPAUTH: add CURLAUTH_NTLM
CURLOPT_PROXYAUTH: add CURLAUTH_NTLM
set CURLOPT_FOLLOWLOCATION
There is no such thing as an 'anonymous packet' in standard networking parlance. Your client's firewall is making up terms, or there was a miscommunication somewhere along the line before the message got to you. Either way, you're going to need to get clarification from your client or the firewall's vendor or documentation.
I agree with bdonlan. In the context of http requests, "anonymous packets" is vague and ambiguous at best. Maybe they mean there is no referrer code? Or they require http-authentication? Or you need to establish a session key before being able to access the specific url you are requesting? You need actual technical details from your client.
If I want my account holders to be able to have their own sub-domains and even their own domains altogether. Using NGINX as my proxy server, should I create domains for each one in my NGINX conf and have my clients point their domains there or is there reasons why this would be bad? Also, if I do that, how can I pass account-specific (account in Django DB) information in with the request (ie, request from www.spamfoosaccount.com to my server, so I proxy the request back to Apache, but how does my application know that it came from spamfoo's account unless I look at request.HTTP_HOST (which might be the best way, but I don't know until I ask). Thanks in advance.
To know from which domain a request is coming from, you have to use request.META["HTTP_HOST"].
However, do not rely on this value for authentication, it can be forged easily. Authentication should be done in the usual way with django.contrib.session. A request from a specific domain/subdomain should not have more privileges/rights, even when the request contains an authenticated session. Privileges should be given to users/groups of users, not to domains.
Note that browser sessions cannot cross second-level-domains (e.g. session cookie from foo.com wil not be sent to bar.com), it can however be a *.foo.com cookie for all subdomains (if you explicitly set it so).
Let your users point their DNS records to the IP of your server, let NGINX route the request based on the domain to your backend and do normal authentication in Django.
Your question:
how does my application know that it
came from spamfoo's account
I don't know the specifics of your application, but it shouldn't matter where the request came from, but who issued the request (e.g. an authenticated user). You should have a model/field that links your users to their respective domains. When a user is linked to only one domain, the application should assume the user came from that domain. When a user is connected to more than one domain, you can look at request.META["HTTP_HOST"]. If this value matches any of the domains, the user is linked to, it's alright, the value may be forged, but by a user that is linked to that domain nonetheless.