What's the expected behavior of a dependent app when an LDAP user's DN changes? - ldap

Is there any expected/standardized behavior for an app that authenticates via LDAP, when one of its registered users has its DN changed? (Or more generally, when their effective principal changes, which seems to commonly be their DN. I'll say "principal" instead from here, though I usually think "DN".)
Here's an example from Gitlab running into this issue: https://gitlab.com/gitlab-org/gitlab-foss/issues/993
In their case (based on the commit linked in that issue) they seem to address this by using multiple attributes to identify users instead of a single one, so that a single change doesn't prevent them from mapping back to the same LDAP user.
It seems to me the available options would be:
Don't try to prevent the issue but provide some method to change the principal stored (either in-app or via DB modifications)
Try to prevent the issue by picking (automatically or manually by user) a better, static user attribute to use as principal
Try to mitigate the issue by cross-referencing multiple attributes, as in the above links
Which of these would be the expected/"best" approach here, if any?

Related

Restrict access of a connected app (Salesforce)

What is the best way to restrict the scope of a connected app to a set of objects? My current solution is to use the Manage user data via APIs scope but that still grants more access than required.
A solution I see frequently is to create a user with a restricted profile and connect with that user but then you lose context of actions made by users in the connected app so this solution doesn't work
Tricky, you typically don't. (consider posting on https://salesforce.stackexchange.com/, there might be a clever way I didn't think of).
You can flip the connected app from "all users can self authorise" to "admin-approved users are preauthorised" and then allow only certain profiles / permission sets to use the app. But the bulk of it is "just" enabling the connection via API and cutting it to say Chatter only or OpenId identifiers. And that's already an improvement compared to SOAP APIs where you don't have scopes and the app can completely impersonate the user, do everything they can do in UI.
Profiles/permission sets/sharing rules are "the" way even in not immediately obvious situations like Lighting Connect Salesforce to Salesforce or Named Credentials access to another org.
If you can't restrict the visibility with profiles and access to all tables user can see is not acceptable...
you could create series of Apex classes exposing certain queries, updates etc and grant profile access to these classes - but without full api access? You could even let them pass any SOQL (evil) but use with sharing, WITH SECURITY_ENFORCED, stripInaccessible + custom restriction on tables before returning results
you could look into https://developer.salesforce.com/docs/atlas.en-us.238.0.apexref.meta/apexref/apex_class_Auth_ConnectedAppPlugin.htm although I suspect it's run only on connect, not on every request. So at best you could deny access if user has right to see some sensitive data, not great
if there are few objects you need to block updates if done via app - Quiddity might be the way to go. Throw error in a trigger if action started from REST context?
give the Transaction Security trailhead a go. If it looks promising (there's way to check "application" and "queried entities" according to this) - might be a solution. You'll likely have to cough up $ though, last time I checked the cool bits of event monitoring & transaction security were hidden behind an extra paid addon (standalone or bundled with platform encryption and Field Audit Track into Salesforce Shield solution)
2 logins? dedicated user for querying stuff but inserts/updates running as your end user?

dovecot: enabling a secondary password?

We're dealing with an unusual situation involving dovecot that perhaps requires an unusual solution.
We recently required all of our POP/IMAP users to change their passwords, and in almost all cases, they dutifully did so. However, one user has several devices and machines which are repeatedly querying for email, and due to circumstances beyond anyone's control, one of his computers cannot be accessed for at least another few weeks, and therefore, the dovecot password for that user's email access cannot not be changed until that time passes.
Therefore, that computer keeps querying dovecot for email for that user with the old, now invalid password, and those queries fail.
Furthermore, due to various circumstances which are also beyond our control for the time being, we can't have that one user change his password back to the old value on the other machines and devices that he uses.
What we're wondering is whether there is some way that dovecot could be set up to recognize and accept both passwords for this one, specific user. In other words, can we somehow set up a secondary password for this email address so that both the old and the new password will allow this user to access his email?
We are using auth sql by including auth-sql.conf.ext in 10-auth.conf. Perhaps the solution to this problem would to restructure the database we are using for SQL authentication and add one or more columns, and then somehow change the SELECT statement that is used in auth-sql.conf.ext to choose between one of two passwords.
We are willing to attempt this procedure if it's the only option available, but we aren't even sure how it can be done. And in any case, we're hoping that there might be some feature of dovecot that we are unfamilar with which would allow us to set up this one user's dovecot email account to allow two different passwords for authentication without any database changes.
Is there any chance that we could do this?
Thank you in advance.
The link supplied by Allan Wind helped me (thank you!), as well as a couple other things I saw in those dovecot docs which I had overlooked in the past.
It turns out that I can supply a second userdb and passdb block in auth-sql.conf.ext, and they serve as secondary fallbacks if the primary SQL query doesn't return a match. I set up a passwd-file that is usable by both of these which contains the hash of the user's old password, and now, both passwords are working.
For example, the secondary userdb block (which should appear right below the original sql-based userdb block) looks like this:
# Fallback ...
userdb {
driver = passwd-file
args = scheme=md5-crypt username_format=%u /etc/dovecot/extra.userdb
}
The secondary passdb block is identical, except for it being named passdb instead of userdb. It must appear right after the original passdb statement in that same file.
So, all's well that ends well.
Onward!

setting passwordMustChange attribute to "on" in Sun-one LDAP doesn't have any expected effect

I am using JNDI framework to interact with various LDAP servers specifically for Sun one LDAP, I am observing the following:
Use case: If Administrator resets password of any user in Sun-One LDAP server then passwordMustChange attribute is set to "on". As a result user has to change his/her password on next logon. This is what documented.
I am performing same action through JAVA code using JNDI. I observed that this attribute is set to "on" successfully. So programming logic is correct.
But when I logon with that user on LDAP server, it doesn't give any error or pop saying that password has expired and please change your password.
The same use case works as expected in case of Active Directory (AD ) servers
In case of AD, we need to set pwdLastSet to 0. It works and system asks to change password on next logon.
On contrary, same use case does not work for any LDAP flavour such as Sun-One LDAP, ADAM, or Open LDAP.
Please let me know if anybody has observed such issue and suggest me how to fix this.
You're setting it in the wrong place. passwordMustChange is an attribute of the policy, not of a user. It means that if you set the operational attribute pwdReset for any user, he must change his password on next login, and that is advised via a response control when he does so.
That in turn means you must use the password-policy request control when binding a user, and check the response control. It also means that you must use the change-password extended operation when changing the password, rather than just rewriting the attribute.
This also explains why you thought you had to add objectClass=passwordPolicy to the user entry. You don't. You have to define a separate policy object containing a value for passswordMustChange and the other policy attributes, and specify that in the configuration as default policy, or in the user entry as his specific policy if you're going that far.
You need to reread the documentation and distinguish clearly between policy attributes and user operational attributes. They're listed separately.
What code are you using for the extended operation and request/response controls? I had to write mine. I posted it on the Sun Java forums several years ago: is it that code? Just curious.
Unfortunately there is no standard for this kind of feature (there's an internet draft, expired and which is partially implemented in different servers).
Depending on your versions of Sun Directory Server, there are different ways to do this (SunDS 6.x introduced a new password policy based on the Internet Draft).
With 5.x, I seem to recall that the passwordExpirationTime would take a specific value when the password is expired. The server will return a PasswordExpired Control part of the Bind response saying that it has expired.
With 6.x and beyond, the pwdReset operational attribute is set to true. The server will either return the PasswordExpired Control, or a PwdPolicyControl response if you've set the PwdPolicyControl request in the Bind request.

Yii RBAC, Role change in runtime

I am building up a dynamic RBAC system for Yii and I don't know how to handle this problem:
The moderators can change the roles of the Users, furthermore the User can change it too by getting a different qualification (let's say achievement, so s/he can do more stuff and it can happen both ways).
What happens, when the role is changed Backwards (a role with less right) or Forwards (a role with more right) when s/he is logged in? Cannot access the functions he just got the right to use? Or can still access the functions until a logout/relog action?
Thanks your help in advance.
The effect of changing the authorization assignment will be inmediate.
Only the successive calls to IWebUser::checkAccess() issued in the same request may return cached values, since the default implementation of IWebUser, i.e. CWebUser, uses a static attribute to cache the calculated permissions.
To clarify the procedure, you will be calling IAuthManager::revoke() on the old permissions and IAuthManager::assign() on the new ones.
Edit
Sometimes you store session information through the IWebUser::setState() method; if the state of the currently logged user shall change along with the permissions, e.g. you store the current user's role name, you must take this into account and either call IWebUser::clearState() or IWebUser::logout() followed by IWebUser::login() –the latter also clears the cached permissions in the CWebUser implementation.
CWebUser::_access is declared private, so you will have to declare a new attribute if you want to override the default implementation.

is openid.claimed_id static?

I'm reading about Federated Login for Google Account Users to figure out how I can have a user log in to a web application using their Google Account.
So towards the end of the process, Google returns a Google supplied identifier which is appended as openid.claimed_id. This means the web application uses this identifier to recognize the user and allow access to application features and data. My question is, is this identifier static? Can I use this identifier to repeatedly id the same user?
Yes. Consider the openid.claimed_id value to be the username. Especially with Google, but this is true for any OpenID Provider that truly implements 'directed identity', don't consider this username to be correlatible with other web sites. Any other relying party besides your own web site will get a different claimed_id value for the same Google user, by design.
Also, be sure to treat this claimed_id as case sensitive.
The specific answer to your question is found in Googles OpenID API documentation:
The Google-supplied identifier, which has no connection to the user's actual Google account name or password, is a persistent value; it remains constant even if the user changes their Google user name and/or email address. This identifier is also a "directed identity", that is, Google returns a different value to each relying party. Google uses the request parameter openid.realm to recognize the relying party, so if the third-party application decides to change this value, all user identifiers will change.
In fact, I just ran into an instance where the google claimed_id had changed for my test user. I was coming to the end of implementing OpenID into my app, and for no apparently reason the claimed_id in the response data is had changed.
I've been testing with this account for the past couple weeks, and the claimed_id was the same this entire time, as expected. Then wham, changed! I looked at the response data many times to verify, and the underlying code to retrieve the data had not changed.
I'm not sure how to handle this at the moment, but I think this is going to throw me for a loop. After initial authentication, users register to the site (as you might expect) and setup a screen name. How are we to verify it is the same user if the claimed_id had changed? We certainly can't use email address, per best practices.
EDIT
Now I have pie in my face! I missed one little detail, that turned out to be a major detail. I change my development environment and was hosting on a different v-host. This effectively change the realm, and this will change the claimed_id response according to the docs.
This was a good lesson for me, as I was about to implement OID on a subdomain in which realm was being set automatically in my code. Now I saved myself a headache down the road, because I would not have been able to use the same user database across all other sub-domains without breaking identity.
updating realm
MORE INFO
Just as a side note - even if you are developing your OpenID solution for one of your subdomains, it might be prudent for you to specify realm to your top-level domain.
e.g., openid.realm = http://*.yourdomain.com
It will allow you to expand your sign-in page across all your subdomains and keep user identity across them.
(optional) Authenticated realm. Identifies the domain that the end
user is being asked to trust. (Example: "http://*.myexamplesite.com")
This value must be consistent with the domain defined in
openid.return_to. If this parameter is not defined, Google will use
the URL referenced in openid.return_to.