NGINX as conditional reverse proxy. How to set that up? - nginx

I've been battling this question/issue for a while now. And I am kinda stuck at this point, so, please help!
I need to set up a Conditional reverse proxy using NGINX. The Conditional part is based on the result of oath authentication, possible user roles.
Here's example of post auth map that I have:
map $auth_result $out_role {
'group-1' 'admin';
'group-2' 'editor';
'group-3' 'user';
default 'user';
}
I have three services that are behind reverse proxy;
localhost:123 - accepts admin, editor, user
localhost:111 - accepts only admin, editor users
localhost:222 - accepts only admin, editor users
So if user authenticated with user group user then he should always be redirected to localhost:123 and only to that. If user authenticated with admin or editor then he has allowance to all site resources.
I have tried using
location /foo/bar/ {
if($out_prole = 'user') {
return 304 localhost:123; # and be done with it
}
}
but that did not get me anywhere, for nginx not handling it's conditionals conveniently inside location blocks.
Now I'm looking for a way to accomplish that; Should I be setting up different server {...} blocks inside nginx? or maybe there's a way to accomplish this without conditionals?
Please help me find a direction with this problem, for I am stuck.
Thanks,
Vadim

Related

Symfony one application multi subdomains

I have rerouted all the traffic to my main domain let's say www.example.com and my first page is www.example.com/login so any entry in the subdomain will be redirected to main domain so something.example.com/login will end up on the same page as www.example.com/login (but the subdomain will stay in the url). The reason I am doing this is that i have multi 'clients' and 'users' every user is responsible for one or more client and its all set in the database and working perfectly so i can login with user1 i will see some tasks for user1 on client1 and when i login with user2 i will see tasks from user2 on client2 etc...
Now i need to do one more thing to make it look a bit better, when someone opens example.com and login with user1 credentials i want him to be redirected to client1.example.com and at the same time when someone opens client1.example.com i want him to see the logo from that client.
All the database queries and other login issues are handled but i am facing couple of issues:
how to redirect to the correct client (subdomain) ?
and vice versa if a (super admin) user which responsible for managing clients and users logs in how to redirect him to main domain (example.com) without?
One more issue but i think it will be solved when i can solve the other issues is when a user manages more than one client, i want to give him the ability to switch clients something like user1 have a menu to switch to client1 or client2 but any redirection i make is logging the user out. how can i maintain the session with this feature ?
p.s when different users logs in the (theme) colors and logos of the application are being called from database according to the client and thats why i need to read the subdomain on the first page so i can change the login logo according to the subdomain
this is a piece of my code to see how i am achieving this if anyone is interested
$currentUrl = $request->getHttpHost();
$baseUrl = $this->container->getParameter('base_url');
$subdomain = str_replace('.'.$baseUrl, '',$currentUrl);
if (sizeof($user->getClients()) > 0) {
$filter = $this->em->getFilters()->enable(Utils::CLIENT_FILTER_NAME);
if ($user->getLastLoggedInClient() !== null) {
$client = $user->getLastLoggedInClient();
} else {
$client = $user->getClients()->first();
}
if ($client == null) {
throw new ClientNotFoundException();
}
if(!$client->isActive()){
throw new ClientNotActiveException();
}
$this->session->set(Utils::CLIENT_ID_NAME, $client->getId());
$this->session->set('client', $client);
$filter->setParameter(Utils::CLIENT_ID_NAME, $client->getId());
$user->setLastLoggedInClient($client);
$this->em->persist($user);
$this->em->flush();
}
else{
return new RedirectResponse('/logout');
}
return new RedirectResponse('/');
so i think somewhere around here return new RedirectResponse('/'); i need to redirect to the correct subdomain.
Thanks!
When you first realise that a user needs to login (from client1.example.com), put the URL, or 'client1' client-name into a session, readable on www.example.com - or add it to the URL (like https://www.example.com/login/to/client1 - the route would be '/login/to/{clientname}'), or more simply /login?clientname=client1.
When a user has logged in, and been verified to be a member of 'client1', then the redirection would be to a route like 'client_app_dashboard', ['clientname' => 'client1'] - and a route definition of #Route("/", name="client_app_dashboard", host="{clientname}.example.com")
The Symfony docs have information on How to Match a Route Based on the Host.
As for a logo - that would be fetched and displayed based on the $clientname on the www. homepage.

Nginx ldap auth login by different attributes

I need to configure nginx to sign in by two kinds dn :
cn=appname,ou=Applications,o=example.com
uid=username,ou=People,o=example.com
Here is piece of code for ldap server:
ldap_server ldapserver {
url ldaps://ldap.example.com/o=example.com?uid,cn?sub?(..filter for search...)
}
However, only username can be signed in, appname can't.
But if I switch the position of uid and cn for that url, like
url ldaps://ldap.example.com/o=example.com?cn,uid?sub?(..filter for search...)
Then appname can be used to sign, username can't.
Is this nginx-ldap-auth's bug?
From looking at the source, the module appears to currently be designed in this way; it'll just consider the first attribute in your comma-separated list even though the ldap_url_parse function (what the module uses under the hood) supports specifying multiple attributes.
I would add a feature request / issue at https://github.com/kvspb/nginx-auth-ldap/issues.
In the meantime, you can use multiple ldap_server blocks to define two different configurations, one with one attribute and one with the other, such as:
ldap_server ldapserver_one {
url ldaps://ldap.example.com/o=hp.com?uid?sub?(..filter for search...)
}
ldap_server ldapserver_two {
url ldaps://ldap.example.com/o=hp.com?cn?sub?(..filter for search...)
}
location / {
auth_ldap "Authorised Only";
auth_ldap_servers ldapserver_one;
auth_ldap_servers ldapserver_two;
...
}
It'll require making two separate connections to your LDAP server, but it'll work.

Browser ignores cookie if domain is set

I need to share cookie between two web applications deployed on azure (eg. x1.azurewebsites.net, x2.azurewebsites.net)
I thought that all i need to do is to set a domain:
Response.Cookies.Add(new HttpCookie("TEST", "BLE")
{
Domain = "azurewebsites.net"
});
But its not working.
For test purposes I added:
Response.Cookies.Add(new HttpCookie("TEST2", "AQQ"));
And this one works ok - but its available only on x1.azurewebsites.net
So the question is whats wrong with the code above?
Is it possible to share cookie like this?
Maybe this is security issue? - i understand that every application hosted on azuerwebsites will have access to information stored in my cookie
I found my question similar to
Chrome34 ignores cookies with domain ".cloudapp.net"
So the cause of my issue is browser checks the publicsuffix.org list for domains and block cookies for security reasons.
For more info please see:
http://publicsuffix.org/
RFC2109 says, that explicit specified domains must start with a dot.
http://www.ietf.org/rfc/rfc2109.txt

Updating User's Info without allowing user write ability

How could you setup rules on Firebase which would allow a user to become a paid user of your app? For example, if I have the following data structure:
{
users: [
{
isPaid: false
},
{
isPaid: true
}
]
}
How could you setup firebase rules to not allow the user to update it themselves (by fudging a request), but still allow it to be updated automatically when they "pay" for your app?
I've thought about randomly generating a number and asking the user to enter that number or something like that, but I don't think that would work... Has anyone done something like this?
You'll need to have a server process that securely writes the paid flag using a Firebase secret (that can be found on Forge for your Firebase). Set the ".write" rule for /users/isPaid as false - the server code can bypass this rule since it knows the secret. You should call firebaseRef.auth(secret) from your server code first.

ACS - bypassing user redirection to IdP?

I have only recently been looking into ACS, AAL, WAAD and I would like to avoid redirecting users to the login page of their IDP. I want to keep my users within my site and present them with a dropdown to choose who they wish to authenticate with and an area to request a username and password, then acquire token via code. Is this possible?
I have been reviewing some sample applications and produce a quick mock-up, but cant seem to get things working e.g.
_authContext = new AuthenticationContext("https://littledeadbunny.accesscontrol.windows.net");
string enteredEmailDomain = UserNameTextbox.Text.Substring(UserNameTextbox.Text.IndexOf('#') + 1);
IList<IdentityProviderDescriptor> idpdList = _authContext.GetProviders("http://littledeadbunny.com/NonInteractive");
foreach (IdentityProviderDescriptor idpd in idpdList)
{
if (String.Compare(ServiceRealmDropDownList.SelectedValue, idpd.Name, StringComparison.OrdinalIgnoreCase) == 0)
{
Credential credential;
credential = new UsernamePasswordCredential(enteredEmailDomain, UserNameTextbox.Text, PasswordTextbox.Text);
_assertionCredential = _authContext.AcquireToken("http://littledeadbunny.com/NonInteractive", idpd, credential);
return;
}
}
Using the code above, when I try to use the Windows Azure Active Directory User (admin), i get the error "Data at the root level is invalid. Line 1, position 1." where I attempt to acquiretoken.
When I use Google, I get an error "0x8010000C: No identity provider matches the requested protocol".
If there is a working sample? if I am doing something obviously wrong, I would appreciate the correction.
This is not supported for passive identity providers. IdPs like Google, Facebook, etc. don't want other people collecting credentials for them, as this leads to security issues and possible phishing attacks. They also don't support it because they need to be able to show a permission dialog (that screen that asks the user if they want to release data to you) which they can't do without the browser redirecting to them. Furthermore, Google in particular supports two-factor auth, which you couldn't replicate, and generally collecting credentials opens up whole cans of worms around other UI problems such as incorrect or forgotten passwords.
This is also generally a bad user experience, because your users are fairly likely to already be logged in to Google and have cookies there. If so, and if they've already consented to your app, they would just be silently redirected back to you. In your scenario, even if the user is already logged in they'd still have to provide a username/password.
The correct way to do these sorts of logins is to render a browser control in your app that allows the user to log in at their IdP, which is what AAL helps with.
I had the same error, executing a powerscript solved that error
PS C:\windows\system32> $replyUrl = New-MsolServicePrincipalAddresses
-Address https://mydomain.accesscontrol.windows.net/
PS C:\windows\system32> New-MsolServicePrincipal -ServicePrincipalNames
#("https://mydomain.accesscontrol.windows.net/") -DisplayName
"MyDomain Namespace" -Addresses $replyUrl
But i'm stuck anyway with a 403 permission error
If you get any further i would like to know how :)

Resources